Thanks, once again, to Scott McFarlane for working his magic and finding a simple way to make an approach work that I’d convinced myself wasn’t workable. (He took the implementation in my last post and adjusted it to work via a non-static event – something I had tried to do myself, but had somehow failed… I can probably blame it on post-DevDays fatigue… time for a week off, indeed. :-)
Here’s the adjusted PaletteSet2 implementation, with the event no longer defined as static and the trigger happening via an instance rather than being fired statically:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using System;
[assembly: CommandClass(typeof(PaletteSet2))]
namespace Autodesk.AutoCAD.Windows
{
public class PaletteSet2 : PaletteSet
{
// Hold a static pointer to the palette set being closed
public static PaletteSet2 Current = null;
// Our static event to be fired on close
public event EventHandler PaletteSetClosed;
// In the constructor we add an event handler to check
// for changes of state (show/hide)
public PaletteSet2(string name) : base(name)
{
this.StateChanged +=
(s, e) =>
{
// On hide we fire a command to check the state properly
if (e.NewState == StateEventIndex.Hide)
{
// Set the static property to point to our palette
PaletteSet2.Current = this;
// Launch the command quietly
Application.DocumentManager.MdiActiveDocument.
SendStringToExecute(
"CHECKPALETTESETCLOSE ", true, true, false
);
}
};
}
// For some reason we need a default constructor with 0 args
public PaletteSet2()
: base("")
{
}
// Our command implementation
[CommandMethod("CHECKPALETTESETCLOSE", CommandFlags.NoHistory)]
public static void CheckPaletteSetState()
{
// Get the static instance set
PaletteSet2 ps = Current;
// If it's invisible, it has been closed
if (ps != null && !ps.Visible)
{
// Set the static instance to null and fire the
// subscribed event
Current = null;
if (ps.PaletteSetClosed != null)
{
ps.PaletteSetClosed(ps, new EventArgs());
}
}
}
}
}
Here’s the updated command implementation, which can now support events that are different per PaletteSet2 instance (just as things should be):
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
[assembly: CommandClass(typeof(Test.Commands))]
namespace Test
{
public class Commands
{
private static PaletteSet2 _ps1 = null, _ps2 = null;
[CommandMethod("PSTEST")]
public static void CreatePaletteSet()
{
if (_ps1 == null)
{
_ps1 = new PaletteSet2("First PaletteSet to Close");
_ps1.Style =
PaletteSetStyles.NameEditable |
PaletteSetStyles.ShowPropertiesMenu |
PaletteSetStyles.ShowAutoHideButton |
PaletteSetStyles.ShowCloseButton;
_ps1.MinimumSize = new System.Drawing.Size(300, 300);
_ps1.PaletteSetClosed +=
(s, e) =>
{
PaletteSet2 ps = s as PaletteSet2;
if (ps != null)
{
Application.DocumentManager.MdiActiveDocument.
Editor.WriteMessage(
"\n\"{0}\" closed!", ps.Name
);
}
};
}
if (_ps2 == null)
{
_ps2 = new PaletteSet2("Second PaletteSet to Close");
_ps2.Style =
PaletteSetStyles.NameEditable |
PaletteSetStyles.ShowPropertiesMenu |
PaletteSetStyles.ShowAutoHideButton |
PaletteSetStyles.ShowCloseButton;
_ps2.MinimumSize = new System.Drawing.Size(300, 300);
_ps2.PaletteSetClosed +=
(s, e) =>
{
PaletteSet2 ps = s as PaletteSet2;
if (ps != null)
{
Application.DocumentManager.MdiActiveDocument.
Editor.WriteMessage(
"\n\"{0}\" closed!", ps.Name
);
}
};
}
_ps1.Visible = true;
_ps2.Visible = true;
}
}
}
Otherwise the behaviour is (thankfully) the same as that of the last post, while the implementation is clearly much cleaner. I'm not sure how I managed to not get it working, myself, but am just thankful that Scott's around to point out the obvious when it whooshes past me.
And yes, I did queue this (and the next) post up before heading to the Alps for Christmas, so I’m not really here. Just in case you thought I was actually working. :-)