I started looking into the ObjectOverrule class, this week, to see if I could use it to prevent erasure of certain objects. My thinking was that overruling Erase() would allow me to control whether an object was erased or not, simply by my decision whether or not to super-message to the base implementation.
That doesn’t appear to be the case, as whether I call the base implementation or not the object gets erased. I’ll have to confirm that this is expected behaviour, but in the meantime I thought I’d share a version of my code which adds a simple ObjectOverrule to watch for erasure/unerasure of database objects in AutoCAD. It’s not very different from using tools such as ArxDbg/MgdDbg/EventsWatcher to watch for Database.ObjectErased() – it just uses an overrule to do something very similar.
Here’s the C# code to add a command to watch for erasure (WER):
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
namespace WeLikeToWatch
{
public class Commands
{
public class EraseOverrule : ObjectOverrule
{
public override void Erase(DBObject dbObject, bool erasing)
{
base.Erase(dbObject, erasing);
Application.DocumentManager.MdiActiveDocument.Editor.
WriteMessage(
"\n{0} {1} ({2}).",
erasing ? "Erasing" : "Unerasing",
dbObject.GetType().Name,
dbObject.Handle
);
}
}
static EraseOverrule _theOverrule = null;
[CommandMethod("WER")]
static public void WatchErasure()
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
if (_theOverrule == null)
{
_theOverrule = new EraseOverrule();
ObjectOverrule.AddOverrule(
RXObject.GetClass(typeof(DBObject)),
_theOverrule,
false
);
ObjectOverrule.Overruling = true;
ed.WriteMessage("\nWatching erasure of database objects.");
}
else
{
ObjectOverrule.RemoveOverrule(
RXObject.GetClass(typeof(DBObject)),
_theOverrule
);
_theOverrule.Dispose();
_theOverrule = null;
ed.WriteMessage(
"\nNo longer watching erasure of database objects."
);
}
}
}
}
I’ll check in on the behaviour I’m seeing, to make sure my expectations are appropriate: I can see why arbitrarily stopping Erase() from being called on any object might be contentious (disastrous?), so it may simply be an “additive” event, rather than allowing outright prevention/replacement of the call.
In the meantime, try calling the WER command and performing some simple AutoCAD commands: you should find it interesting to see some of what’s going on under the hood.
The above code could clearly watch for other events available from ObjectOverrule, with very little effort:
- Cancel
- Close
- DeepClone
- Open
- WblockClone
But that’s for another day. :-)