.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Create Toolbar with C#

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
HelloWorlddd
10065 Views, 11 Replies

Create Toolbar with C#

    I have created quite a few AutoCAD commands, but I think it’s a troublesome thing let users remember the shortcuts, I want to create a toolbar for these commands through C# code, I hope someone can provide a simple and detailed tutorial, step by step is the best..


Sincerely thank

11 REPLIES 11
Message 2 of 12
DouceDeux
in reply to: HelloWorlddd

Toolbars are a big topic. Took me weeks of search and testing to get the following code down. Make of it what you will. Sorry but I'm not explaining it line by line. I encourage you to search the forums, the dev blog and the Through the Interface blog as well.

P.S. the .bmp's are project resourses.

 

public void RLCui()
    {
      //Coded by: Lev Villanueva (doucedeux@gm**l.com)
      
      Document newDocument = Application.DocumentManager.MdiActiveDocument;
      Database newDatabase = newDocument.Database;

      bool exists = false;
      String mainCUI = Application.GetSystemVariable("MENUNAME").ToString() + ".cuix";      
      CustomizationSection mainCS = new CustomizationSection(mainCUI, false);
      String baseFolder = mainCUI.Replace(mainCS.CUIFileBaseName + ".cuix", "");
      PartialCuiFileCollection newPCFC = mainCS.PartialCuiFiles;
      String cuiFileToSend = "\"" + baseFolder + "RL.cuix" + "\"";
      String test1 = mainCUI.Replace(mainCS.CUIFileBaseName + ".cuix", "RL.cuix");
      if (newPCFC.Contains(mainCUI.Replace(mainCS.CUIFileBaseName + ".cuix", "RL.cuix")))
      {
        if( Forms.MessageBox.Show("CUI already exist.\nDelete?", "CUI Exists", Forms.MessageBoxButtons.YesNo, Forms.MessageBoxIcon.Information, Forms.MessageBoxDefaultButton.Button1, 0) == Forms.DialogResult.No)
          return;
        exists = true;
      }

      Rebars.Properties.Resources.RLQUAD_16.Save(baseFolder + "RLQUAD16.bmp");
      Rebars.Properties.Resources.RLQUAD_32.Save(baseFolder + "RLQUAD32.bmp");
      Rebars.Properties.Resources.RLXREF_16.Save(baseFolder + "RLXREF16.bmp");
      Rebars.Properties.Resources.RLXREF_32.Save(baseFolder + "RLXREF32.bmp");
      Rebars.Properties.Resources.RLSI_16.Save(baseFolder + "RLSI16.bmp");
      Rebars.Properties.Resources.RLSI_32.Save(baseFolder + "RLSI32.bmp");
      Rebars.Properties.Resources.RLOSA_16.Save(baseFolder + "RLOSA16.bmp");
      Rebars.Properties.Resources.RLFILTRAR_16.Save(baseFolder + "RLFILTRAR16.bmp");
      Rebars.Properties.Resources.RLEXPORTAR_16.Save(baseFolder + "RLEXPORTAR16.bmp");

      CustomizationSection newCS = new CustomizationSection();
      newCS.MenuGroupName = "RL";
      
      MacroGroup newMG = new MacroGroup("RLMacros", newCS.MenuGroup);

      MenuMacro newMM1 = new MenuMacro(newMG, "RL Xref", "^C^CRLXREF", "ID_RL_Xref");
      newMM1.macro.SmallImage = baseFolder + "RLXREF16.bmp";
      newMM1.macro.LargeImage = baseFolder + "RLXREF32.bmp";
      newMM1.macro.HelpString = "Anexar plano original bajo determinadas especificaciones";
      newMM1.macro.CLICommand = "RLXREF";
      
      MenuMacro newMM2 = new MenuMacro(newMG, "RL Quadrant", "^C^CRLQUAD", "ID_RL_Quad");
      newMM2.macro.SmallImage = baseFolder + "RLQUAD16.bmp";
      newMM2.macro.LargeImage = baseFolder + "RLQUAD32.bmp";
      newMM2.macro.HelpString = "Crear cuadrante relacionado a una losa";
      newMM2.macro.CLICommand = "RLQUAD";

      MenuMacro newMM3 = new MenuMacro(newMG, "RL si", "^C^CRLSI", "ID_RL_si");
      newMM3.macro.SmallImage = baseFolder + "RLSI16.bmp";
      newMM3.macro.LargeImage = baseFolder + "RLSI32.bmp";
      newMM3.macro.HelpString = "Dibujar refuerzos tipo s e i de una losa";
      newMM3.macro.CLICommand = "RLSI";

      MenuMacro newMM4 = new MenuMacro(newMG, "RLosa", "^C^CRLOSA", "ID_RLOSA");
      newMM4.macro.SmallImage = baseFolder + "RLOSA16.bmp";
      newMM4.macro.HelpString = "Crear refuerzos de losa";
      newMM4.macro.CLICommand = "RLOSA";

      MenuMacro newMM5 = new MenuMacro(newMG, "RL Filtrar", "^C^CRLFILTRAR", "ID_RLFILTRAR");
      newMM5.macro.SmallImage = baseFolder + "RLFILTRAR16.bmp";
      newMM5.macro.HelpString = "Filtrar de entre los refuerzos de losa para su visualización en el plano";
      newMM5.macro.CLICommand = "RLFILTRAR";

      MenuMacro newMM6 = new MenuMacro(newMG, "RL Exportar", "^C^CRLEXPORTAR", "ID_RLEXPORTAR");
      newMM6.macro.SmallImage = baseFolder + "RLEXPORTAR16.bmp";
      newMM6.macro.HelpString = "Exportar refuerzos a archivos de Excel. Se pedirá un nombre para el archivo.";
      newMM6.macro.CLICommand = "RLEXPORTAR";
      
      Toolbar newT = new Toolbar("RL", newCS.MenuGroup);
      ToolbarButton newButton1 = new ToolbarButton("ID_RL_Xref", "RL Xref", newT, -1);
      ToolbarButton newButton2 = new ToolbarButton("ID_RL_Quad", "RL Quadrant", newT, -1);
      ToolbarButton newButton3 = new ToolbarButton("ID_RL_si", "RL si", newT, -1);
      ToolbarButton newButton4 = new ToolbarButton("ID_RLOSA", "RLosa", newT, -1);
      newButton4.DrawSeparator = true;
      ToolbarButton newButton5 = new ToolbarButton("ID_RLFILTRAR", "RL Filtrar", newT, -1);
      ToolbarButton newButton6 = new ToolbarButton("ID_RLEXPORTAR", "RL Exportar", newT, -1);

      newT.ToolbarItems.Add(newButton2);
      newT.ToolbarItems.Add(newButton1);
      newT.ToolbarItems.Add(newButton3);
      newT.ToolbarItems.Add(newButton4);
      newT.ToolbarItems.Add(newButton5);
      newT.ToolbarItems.Add(newButton6);

      StringCollection newSC = new StringCollection();
      int i = 1;
      for (; i < mainCS.MenuGroup.PopMenus.AllAliases.Count; i++)
      {
        if (!mainCS.MenuGroup.PopMenus.AllAliases.Contains("POP" + i.ToString()))
          break;
      }

      newSC.Add("POP" + i.ToString());
      PopMenu newPopMenu = new PopMenu("RL Menu", newSC, "ID_RLPop"   , newCS.MenuGroup);
      PopMenuItem newPMI1 = new PopMenuItem(newMM1, "RL Xref"    , newPopMenu, -1);
      PopMenuItem newPMI2 = new PopMenuItem(newMM2, "RL Quadrant", newPopMenu, -1);
      PopMenuItem newPMI3 = new PopMenuItem(newMM3, "RL si"      , newPopMenu, -1);
      PopMenuItem newPMI4 = new PopMenuItem(newMM4, "RLosa"      , newPopMenu, -1);      
      PopMenuItem newPMI5 = new PopMenuItem(newMM5, "RL Filtrar" , newPopMenu, -1);
      PopMenuItem newPMI6 = new PopMenuItem(newMM6, "RL Exportar", newPopMenu, -1);
      
      newCS.SaveAs(baseFolder + "RL.cuix");
      


      File.Delete(baseFolder + "RLQUAD16.bmp");
      File.Delete(baseFolder + "RLQUAD32.bmp");
      File.Delete(baseFolder + "RLXREF16.bmp");
      File.Delete(baseFolder + "RLXREF32.bmp");
      File.Delete(baseFolder + "RLSI16.bmp");
      File.Delete(baseFolder + "RLSI32.bmp");
      File.Delete(baseFolder + "RLOSA16.bmp");
      File.Delete(baseFolder + "RLFILTRAR16.bmp");
      File.Delete(baseFolder + "RLEXPORTAR16.bmp");           

      Directory.CreateDirectory(baseFolder + "Extended Help");
      System.IO.File.WriteAllText(baseFolder + @"Extended Help\RLEH.xaml", Rebars.Properties.Resources.RLEH);
      Directory.CreateDirectory(baseFolder + @"Extended Help\Images");
      Rebars.Properties.Resources.EH_RLXREF.Save(baseFolder + @"Extended Help\Images\" + "EH_RLXREF.png");
      Rebars.Properties.Resources.EH_RLQUAD.Save(baseFolder + @"Extended Help\Images\" + "EH_RLQUAD.png");
      Rebars.Properties.Resources.EH_RLSI.Save(baseFolder + @"Extended Help\Images\" + "EH_RLSI.png");

      //File.Copy(baseFolder + "RL.cuix", baseFolder + "RL.zip", true);
      
      //Directory.CreateDirectory(baseFolder + "Temp");

      using (ZipFile newZF = new ZipFile(baseFolder + "RL.cuix"))
      {
        ZipEntry newZE = newZF["MenuGroup.cui"];
        newZE.Extract(baseFolder, ExtractExistingFileAction.OverwriteSilently);


        FileStream oldFS = new FileStream(baseFolder + "MenuGroup.cui", FileMode.Open, FileAccess.Read);
        FileStream newFS = new FileStream(baseFolder + "temp.cui", FileMode.Create, FileAccess.Write);
        StreamReader oldSR = new StreamReader(oldFS);
        StreamWriter newSW = new StreamWriter(newFS);
        String line;

        for (int j = 1; j <= 3; j++)
        {
          do
          {
            line = oldSR.ReadLine();
            if (line == null) break;
            newSW.WriteLine(line);
          } while (!line.Contains(@"<CLICommand"));

          if (line != null)
          {
            newSW.WriteLine(@"<ToolTip>");
            newSW.WriteLine(@"<ExtendedContent UriSource=""" + baseFolder + @"Extended Help\RLEH.xaml"" SourceKey=""RLEH_CMD_00" + j.ToString() + @""" />""");
            newSW.WriteLine(@"</ToolTip>");
          }
        }

        while ((line = oldSR.ReadLine()) != null)
          newSW.WriteLine(line);

        newSW.Dispose();
        oldSR.Dispose();
        oldFS.Dispose();
        newFS.Dispose();

        File.Delete(baseFolder + "MenuGroup.cui");
        System.IO.File.Move(baseFolder + "temp.cui", baseFolder + "MenuGroup.cui");
        newZF.RemoveEntry("MenuGroup.cui");
        newZF.AddFile(baseFolder + "MenuGroup.cui", @"\");
        newZF.Save();
        //System.IO.File.Move(baseFolder + "temp.zip", baseFolder + "RL.cuix");
        File.Delete(baseFolder + "MenuGroup.cui");
      }

      object oldCmdEcho = Application.GetSystemVariable("CMDECHO");
      object oldFileDia = Application.GetSystemVariable("FILEDIA");
      Application.SetSystemVariable("CMDECHO", 0);
      Application.SetSystemVariable("FILEDIA", 0);
      if (exists)
        newDocument.SendStringToExecute("_.cuiunload " + "RL" + " ", false, false, false);

      newDocument.SendStringToExecute("_.cuiload " + cuiFileToSend + " ", false, false, false);
      newDocument.SendStringToExecute("(setvar \"FILEDIA\" " + oldFileDia.ToString() + ")(princ) ", false, false, false);
      newDocument.SendStringToExecute("(setvar \"CMDECHO\" " + oldCmdEcho.ToString() + ")(princ) ", false, false, false);

 

Message 3 of 12
joantopo
in reply to: DouceDeux

Read this:

http://forums.autodesk.com/autodesk/attachments/autodesk/152/26712/1/CP205-2_Mike_Tuersley.pdf

 

You can change VB.Net to C# with a conversor:

http://www.developerfusion.com/tools/convert/vb-to-csharp/

Autocad C3D 2019 SP3, 2020 & 2021
Intel I9 9900K with frontal watercooler alphacool eisbaer 360 (original fans mounted in pull)- 3 fans Corsair 120 ML PRO in push.
MOBO Gygabyte Z390 Aorus Master- Corsair RGB Vengeance 64GB RAM (4x16) CL16
Nvidia Quadro RTX 4000
Samsung 970 EVO PLUS 1TB (unit C). Samsung 970 PRO 512GB (for data)
Power Supply: Corsair TX850M PLUS


Descubre mi programa VisorNET para Civil 3D:
https://apps.autodesk.com/CIV3D/es/Detail/Index?id=appstore.exchange.autodesk.com%3avisornet_windows32and64%3aes
Message 4 of 12
HelloWorlddd
in reply to: joantopo

   I don’t want a Docking Palette, just Toolbar

   For example, draw a line, there is sample code, so I study it will be very convenient
   There also should be sample code for how to creat a very simple Toolbar, and have a button, and the button can execute a esay function, just like output a string.
   I hope to find a such sample code, then I can start easily


   Sincerely thanks

 

Message 5 of 12
HelloWorlddd
in reply to: HelloWorlddd

ToolBar.PNG

 

  Just like this Toolbar, First I want to know how to creat a simplest toolbar that just have one button, click this button just output "Hello"

 I need more help, clear and easy, thanks

 

Message 6 of 12
SENL1362
in reply to: HelloWorlddd

Any reason why not creating a Ribbon Panel?
The Toolbar technology is a relic from the old days.
You find more samples creating Ribbon style menu's.
Message 7 of 12
jeff
in reply to: SENL1362

Just create a partial CUI and create your commands then you can just drag them on Ribbon Panels, Menus, Toolbars, etc.......

 

cui.PNG

 

 

 

 

 

 

acadcui.PNG

 

 

 

 

 

 

 

 

 

 

 

 

You can also find your answers @ TheSwamp
Message 8 of 12
HelloWorlddd
in reply to: jeff

   I hope interface and functionality together, but as I demonstrate below, I only know a way to separate treatment. I want to some friends can help me

 

   Achieve functional

   Below is a very simple command written in C #, Just only need be compiled into dll file, and then enter NETLOAD load the dll file from AutoCAD, and enter HW from a command prompt, it will output “Hello World”

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
[assembly: CommandClass(typeof(MyNameSpace.HelloWorld))]
namespace MyNameSpace
{
class HelloWorld
    {
        [CommandMethod("HW")]
        public void hello()
        {
            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Database acCurDb = acDoc.Database;
            acDoc.Editor.WriteMessage("\nHello World");
        }
    }
}

 

   Automatically loaded

   Below method copy from AutoCAD. NET Developer's Guide directly,It let the program to get automatic loading function

public void RegisterMyApp()
{
  string sProdKey = HostApplicationServices.Current.RegistryProductRootKey;
  string sAppName = "MyApp";
  RegistryKey regAcadProdKey = Registry.CurrentUser.OpenSubKey(sProdKey);
  RegistryKey regAcadAppKey = regAcadProdKey.OpenSubKey("Applications", true);
  string[] subKeys = regAcadAppKey.GetSubKeyNames();
  foreach (string subKey in subKeys)
  {
      if (subKey.Equals(sAppName))
      {
          regAcadAppKey.Close();
          return;
      }
  }
  string sAssemblyPath = Assembly.GetExecutingAssembly().Location;
  RegistryKey regAppAddInKey = regAcadAppKey.CreateSubKey(sAppName);
  regAppAddInKey.SetValue("DESCRIPTION", sAppName, RegistryValueKind.String);
  regAppAddInKey.SetValue("LOADCTRLS", 14, RegistryValueKind.DWord);
  regAppAddInKey.SetValue("LOADER", sAssemblyPath, RegistryValueKind.String);
  regAppAddInKey.SetValue("MANAGED", 1, RegistryValueKind.DWord);
  regAcadAppKey.Close();
}

 

 

   Interface Design

   Now I know how to creat commands, how to load, how to load automatically, and finally I intend to design an interface
   But the only way I know is to create . cuix file by Customize User Interface Editor ,add toolbar, buttons, icons, and macros as shown below

Customize User Interface Editor.PNG

 

   I recall myToolbar, then click the only button with mouse, the program is executed HW command as follows

nameSpace.PNG

 

   but there is a problem, the interface file. cuix and functional document .dll are two files, the user needs to load separately, do not feel good

 

 

 

  I'm wondering how I deal with the above problems
   I think there should be a conventional method, possibly, using C # code to achieve the interface and achieve the functional at the same time, and finally compiled into olny one .dll file
   If, as I suspect, and I hope I can find some C # code
   Sincerely thanks

 

 

Message 9 of 12
HelloWorlddd
in reply to: HelloWorlddd

   I think I found a solution,
   If anyone encountered this problem
   Can refer to
   http://through-the-interface.typepad.com/through_the_interface/2007/05/creating_a_part.html

Message 10 of 12
HelloWorlddd
in reply to: HelloWorlddd

   Function create by C #, and then compiled into dll files, functions automatically loaded by RegisterMyApp() , it’s referenced from AutoCAD. NET Developer's Guide,then the command will auto load very time.

 

   User interface design by Customize User Interface Editor, and then save as .cuix file, load the user interface using the following code, in fact, equivalent to input CUILOAD in command prompt, but this CUILOAD need only be entered once, it does not need to load very time

 

   Here is the way I take, they can be set simultaneously, only one time, perhaps there is a better way, but now I only know this way

 

RegisterMyApp()
{
_cuiload
}

 

UnRegisterMyApp()
{
_cuiunload
}

 the following code is copy form http://forums.autodesk.com/t5/NET/Accessing-toolbars-and-buttons-programatically/m-p/3182594/highlig...

string flName = csGavin.CUIFileBaseName;
Application.SetSystemVariable("FILEDIA",0);
Application.DocumentManager.MdiActiveDocument.SendStringToExecute("_cuiunload " + flName + " ",false,false,false);
Application.DocumentManager.MdiActiveDocument.SendStringToExecute("_cuiload " + flName + " filedia 1 ",false,false,false);

 

Message 11 of 12
dgorsman
in reply to: HelloWorlddd

We use several professionally developed programs, many of which provide separate CUIx files and some of which auto-create user interface elements.  There is little to no effort to load a provided CUIx and use them within our system, but the ones which use programmatically created content are very unfriendly to workspaces.

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


Message 12 of 12

could you tell me what dlls you used in that project

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost