Finding out when a custom PaletteSet is closed in AutoCAD using .NET

I've just come back from the last of the European DevDays in the UK. It was fun being back in my home country so close to Christmas, and the event itself seemed to go well. It was great to catch up with some developers I've known since my early years at Autodesk, some of whom stayed on for dinner and then the DevLab we held yesterday in the brand new office Autodesk Ltd. has just moved into in Farnborough.

A really interesting question came up during the DevLab, and it's one that has been asked before: how do you respond to the "close" of a custom PaletteSet in your code? For example, it's quite common for the closing of project-related palettes to update the current drawing, in some way (perhaps clearing graphics or performing some other action).

The StateChanged event tells you when a palette set is hidden or shown, but it reports that the dialog has been hidden even when closed (basically as we don't really close the palette set when the user hits the "X", we just hide it).

One common suggestion is not to display the standard close button โ€“ by not using the PaletteSetStyles.ShowCloseButton option when creating the palette set โ€“ but having a custom close button makes the user interface inconsistent.

I found one approach to address this: from the StateChanged event handler, send a command to the command-line that can check the visibility of the palette set, and take appropriate action when it has been hidden.

Here's some C# code that demonstrates the technique. Note that the command we're calling is not exposed for the user (we use the CommandFlags.NoHistory option when defining it) and doesn't get echoed to the command-line when we fire it, which makes the approach less ugly.

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Windows;

 

namespace PaletteTest

{

  public class Commands

  {

    private static PaletteSet _ps = null;

 

    [CommandMethod("PSTEST")]

    public static void CreatePaletteSet()

    {

      if (_ps == null)

      {

        _ps = new PaletteSet("PaletteSet to Close");

        _ps.Style =

          PaletteSetStyles.NameEditable |

          PaletteSetStyles.ShowPropertiesMenu |

          PaletteSetStyles.ShowAutoHideButton |

          PaletteSetStyles.ShowCloseButton;

 

        _ps.MinimumSize = new System.Drawing.Size(300, 300);

 

        _ps.StateChanged +=

          (s, e) =>

            {

              Application.DocumentManager.MdiActiveDocument.

                SendStringToExecute(

                  "CHECKPALETTESETCLOSE ", true, true, false

                );

            };

      }

      _ps.Visible = true;

    }

 

    [CommandMethod("CHECKPALETTESETCLOSE", CommandFlags.NoHistory)]

    public static void CheckPaletteSetState()

    {

      if (_ps != null && !_ps.Visible)

      {

        Application.DocumentManager.MdiActiveDocument.Editor.

          WriteMessage("\n\"{0}\" closed!", _ps.Name);

      }

    }

  }

}

When we run the PSTEST command, a custom (empty) palette gets displayed. When this gets closed by the user, a message should get printed to the command-line to indicate the palette set was closed (mentioning its name).

This approach is OK, but gets unwieldy if you want to use it to manage multiple palette set dialogs at the same time. In the next post, we'll wrap the code into a custom class exposing an event that can be subscribed to, which should be much more usable for such situations.

10 responses to “Finding out when a custom PaletteSet is closed in AutoCAD using .NET”

  1. Thanks Kean,

    This solved my problem.

    If one Paletteset containts more than one palettes, how can I set one of the palette on top through code?

    Thanks

  2. Hi Yaqi,

    Glad it helped you.

    Your question isn't specifically related to this post, so I'm going to suggest you either contact the ADN team (if you're a member) or post it to the AutoCAD .NET Discussion Group.

    Regards,

    Kean

  3. Hate to have to ask this, but since a PaletteSet can be closed at any time, including while a command is in progress, what happens in that case?

  4. Kean Walmsley Avatar

    I have some recollection of it working just fine (as the command gets called transparently), although I may be misremembering.

    You can always adjust the behaviour to cancel any current command by prefixing with escape characters, should you so wish, of course.

    Kean

  5. Hi Kean,

    I came across a comment made by Tony T regarding the PaletteSet constructor overloads:
    forums.autodesk.com/t5/NET/PaletteSet-Title-Command-GUID-Confusion/td-p/2661021

    It seems that the constructor's name parameter actually does two things:

    1. Sets the title text for the palette UI window.

    2. Sets the name of the command that will automatically be run if the palette was opened the last time you exited AutoCAD.

    I discovered after some research that the palette guids (as well as palette command names for startup) get stored in the Profile.aws xml file located here:

    C:Users<username>AppDataRoamingAutodeskAutoCAD XXXXRXX.XenuSupportProfiles<profilename>Profiles.awt

    Anyways to get to the point, it seems that if you want your palette to open the next time you open AutoCAD, you should set the PaletteSet constructor's name parameter to the name of your command that shows your palette, as well as specifying a guid. So in your case this would be:

    _ps1 = new PaletteSet("PSTEST", new Guid("6B9B3B17-18C0-44D3-9565-4C2324731F28"));

    You of course would need to make sure the "PSTEST" command was set up so that is was available at startup (i.e. using the registry or autoloader).

    If you want to rename the palette's UI title, you can set the Name property in a seperate statement after the constructor. This doesn't seem to have any effect on the startup command workings.

    Unfortunately the .NET ObjectARX docs don't seem to say much about this. Seems like the PaletteSet really should have different properties (i.e. RestartCommandName and Title) but that's how it goes.

    None of the code samples I have seen mention this. Might be a good post for someone, providing an overview of how the guid system works with the awt files. Perhaps over on adndevblog.typepad.com/auto....

    Sorry, bit of a long one ๐Ÿ™‚

    Art

  6. Correction, awt file path should be:

    C:\Users\<username>\AppData\Roaming\Autodesk\<autocad xxxx="">\R<xx.x>\enu\Support\Profiles\<profilename>\Profiles.awt

  7. Apologies keep forgetting my html tags ๐Ÿ™‚

    C:\Users\<UserName>\AppData\Roaming\Autodesk\AutoCAD <XXXX>\R<XX.X>\enu\Support\Profiles\<ProfileName>\Profiles.awt

  8. Kean Walmsley Avatar

    Great suggestion, Art. I've used the mechanism myself, in the past, but neglected to do so for this particular test example.

    I'll pass it on to Stephen to see if someone in ADN can document this.

    Kean

  9. It seems like dragging the PaletteSet from or to docking triggers the check for if it is being closed. I can't seem to seperate docking/undocking and closing the PaletteSet. Comments?

  10. That's indeed one of the issues that is trying to be addressed by this more recent post:

    keanw.com/2011/12/creating-a-custom-paletteset-class-exposing-a-close-event-inside-autocad-using-net-take-2.html

    Kean

Leave a Reply to Yaqi Cancel reply

Your email address will not be published. Required fields are marked *