December 2014

Sun Mon Tue Wed Thu Fri Sat
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      










« Automating batch printing of DWF files using Design Review 2008 | Main | Using a jig from .NET to multiply insert AutoCAD blocks »

May 14, 2007

Creating a partial CUI file using .NET and loading it inside AutoCAD

I started to address this topic during this previous post, but it seemed like it was worth coming back to.

This time I'm looking at a different technique: to create our own partial CUI file programmatically using the Autodesk.AutoCAD.Customization functionality, save it to disk and then make sure it's loaded at the beginning of every subsequent AutoCAD session.

I'm not going to focus on adding menus etc. into AutoCAD's list - that's left for a future post - this is mainly about the logic needed to make sure a CUI is created and loaded.

Here's some C# code I put together (with the help of some pointers I took from Wayne Brill, a member of our DevTech Americas team). There's more than one way to skin a cat, as they say, but this seems a reliable way to make sure our partial menu is created and loaded. By the way, you'll need to add AcCui.dll as an assembly reference to your project for this code to build.

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Customization;

using System;

using System.Collections.Specialized;


namespace PartialCUI

{

  public class Commands : IExtensionApplication

  {

    public void Initialize()

    {

      BuildMenuCUI();

    }

    public void Terminate()

    {

    }

    [CommandMethod("bm")]

    public void BuildMenuCUI()

    {

      const string myCuiFile = "c:\\kean.cui";

      const string myCuiFileToSend = "c:/kean.cui";

      const string myCuiSectionName = "Kean";


      Editor ed =

        Application.DocumentManager.MdiActiveDocument.Editor;


      string mainCui =

        Application.GetSystemVariable("MENUNAME") + ".cui";

      CustomizationSection cs =

        new CustomizationSection(mainCui);

      PartialCuiFileCollection pcfc = cs.PartialCuiFiles;


      if (pcfc.Contains(myCuiFile))

      {

        ed.WriteMessage(

          "\nCustomization file \""

          + myCuiFile

          + "\" already loaded."

        );

      }

      else{

        if (System.IO.File.Exists(myCuiFile))

        {

          ed.WriteMessage(

            "\nCustomization file \""

            + myCuiFile

            + "\" exists - loading it."

          );

          LoadMyCui(myCuiFileToSend);

        }

        else

        {

          ed.WriteMessage(

            "\nCustomization file \""

            + myCuiFile

            + "\" does not exist - building it."

          );


          // Create a customization section for our partial menu

          CustomizationSection pcs = new CustomizationSection();

          pcs.MenuGroupName = myCuiSectionName;


          // Let's add a menu group, with two commands

          MacroGroup mg =

            new MacroGroup(myCuiSectionName, pcs.MenuGroup);

          MenuMacro mm1 =

            new MenuMacro(mg, "Cmd 1", "^C^CCmd1", "ID_MyCmd1");

          MenuMacro mm2 =

            new MenuMacro(mg, "Cmd 2", "^C^CCmd2", "ID_MyCmd2");


          // Now let's add a pull-down menu, with two items

          StringCollection sc = new StringCollection();

          sc.Add("POP15");

          PopMenu pm =

            new PopMenu(

            myCuiSectionName,

            sc,

            "ID_MyPop1",

            pcs.MenuGroup

          );

          PopMenuItem pmi1 =

            new PopMenuItem(mm1, "Pop Cmd 1", pm, -1);

          PopMenuItem pmi2 =

            new PopMenuItem(mm2, "Pop Cmd 2", pm, -1);


          // Finally we save the file and load it

          pcs.SaveAs(myCuiFile);

          LoadMyCui(myCuiFileToSend);

        }

      }

    }


    private void LoadMyCui(string cuiFile)

    {

      // This load technique sends a LISP string to the

      // command line (which avoid us having to set FILEDIA

      // to 0) after setting CMDECHO to 0, to minimize

      // what's displayed.

      // We make sure the LISP string resets the  value of

      // CMDECHO at the end (the string is executed

      // asynchronously, so we don't have the chance to do

      // it in our calling function).


      Document doc =

        Application.DocumentManager.MdiActiveDocument;


      object oldCmdEcho = Application.GetSystemVariable("CMDECHO");

      Application.SetSystemVariable("CMDECHO", 0);

      doc.SendStringToExecute(

        "(command \"_.CUILOAD\" \""

        + cuiFile

        + "\")(setvar \"CMDECHO\" "

        + oldCmdEcho

        + ")(princ) "

        , false, false, false

      );

    }

  }

}

Here's what happens when we first load our module:

Command: netload

Customization file "c:\kean.cui" does not exist - building it.

Command:

Customization file loaded successfully. Customization Group: KEAN

Command:

Here's what happens when we then run our manual command - "bm" - which calls the same code:

Command: bm

Customization file "c:\kean.cui" already loaded.

Command:

Once created and loaded, the partial menu should be loaded automatically on AutoCAD startup - as shown by the running the CUILOAD command:

Cui_loaded

If we then unload the file and launch AutoCAD again, loading our module, we see this:

Command: netload

Customization file "c:\kean.cui" exists - loading it.

Command:

Customization file loaded successfully. Customization Group: KEAN

Command:

Update:

The above implementation of the LoadMyCui function has some unfortunate behaviour: it doesn't actually cause the menu to be added to the menu bar. Calling CUILOAD from LISP, should be identical to calling the command directly, but in this case it doesn't appear to be. Thanks to Hongxian Qin, from DevTech China, for analysing the problem. The following implementation works as the code was designed to:

private void LoadMyCui(string cuiFile)

{

  Document doc =

    Application.DocumentManager.MdiActiveDocument;


  object oldCmdEcho =

    Application.GetSystemVariable("CMDECHO");

  object oldFileDia =

    Application.GetSystemVariable("FILEDIA");


  Application.SetSystemVariable("CMDECHO", 0);

  Application.SetSystemVariable("FILEDIA", 0);


  doc.SendStringToExecute(

    "_.cuiload "

    + cuiFile

    + " ",

    false, false, false

  );

  doc.SendStringToExecute(

    "(setvar \"FILEDIA\" "

    + oldFileDia.ToString()

    + ")(princ) ",

    false, false, false

  );

  doc.SendStringToExecute(

    "(setvar \"CMDECHO\" "

    + oldCmdEcho.ToString()

    + ")(princ) ",

    false, false, false

  );

}

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83452464869e200d83514d50b53ef

Listed below are links to weblogs that reference Creating a partial CUI file using .NET and loading it inside AutoCAD:

blog comments powered by Disqus

Feed/Share

10 Random Posts