To follow on from the last post, we're now going to take a look at adding custom menu items to the default context menu in AutoCAD. The default menu appears when the user right-clicks on the drawing but has no objects selected. This is a good place to put application commands, for instance.
The approach is very similar to the previous one, although I've added some additional commands to control adding and removing the various menus in addition to relying on the module's initialization callback.
Some other notes:
- We're not just adding a single menu item, but are using a cascading menu - three menu items underneath a main application menu item.
- Once again we're using the Autodesk.AutoCAD.Internal namespace (which is unsupported and liable to change, and needs the AcMgdInternal.dll assembly referenced), to use the PostCommandPrompt() function. We would not need this if we called our commands via SendStringToExecute(), of course.
Here's the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.Internal;
using System;
namespace ContextMenuApplication
{
public class Commands : IExtensionApplication
{
public void Initialize()
{
CountMenu.Attach();
ApplicationMenu.Attach();
}
public void Terminate()
{
CountMenu.Detach();
ApplicationMenu.Detach();
}
[CommandMethod("ADDCONTEXT")]
static public void AttachContextMenus()
{
CountMenu.Attach();
ApplicationMenu.Attach();
}
[CommandMethod("NOCONTEXT")]
static public void DetachContextMenus()
{
CountMenu.Detach();
ApplicationMenu.Detach();
}
[CommandMethod("COUNT", CommandFlags.UsePickSet)]
static public void CountSelection()
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
PromptSelectionResult psr = ed.GetSelection();
if (psr.Status == PromptStatus.OK)
{
ed.WriteMessage(
"\nSelected {0} entities.",
psr.Value.Count
);
}
}
}
public class CountMenu
{
private static ContextMenuExtension cme;
public static void Attach()
{
if (cme == null)
{
cme = new ContextMenuExtension();
MenuItem mi = new MenuItem("Count");
mi.Click += new EventHandler(OnCount);
cme.MenuItems.Add(mi);
}
RXClass rxc = Entity.GetClass(typeof(Entity));
Application.AddObjectContextMenuExtension(rxc, cme);
}
public static void Detach()
{
RXClass rxc = Entity.GetClass(typeof(Entity));
Application.RemoveObjectContextMenuExtension(rxc, cme);
}
private static void OnCount(Object o, EventArgs e)
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
doc.SendStringToExecute("_.COUNT ", true, false, false);
}
}
public class ApplicationMenu
{
private static ContextMenuExtension cme;
public static void Attach()
{
if (cme == null)
{
cme = new ContextMenuExtension();
cme.Title = "Kean's commands";
MenuItem mi1 = new MenuItem("1st");
mi1.Click += new EventHandler(On1st);
cme.MenuItems.Add(mi1);
MenuItem mi2 = new MenuItem("2nd");
mi2.Click += new EventHandler(On2nd);
cme.MenuItems.Add(mi2);
MenuItem mi3 = new MenuItem("3rd");
mi3.Click += new EventHandler(On3rd);
cme.MenuItems.Add(mi3);
}
Application.AddDefaultContextMenuExtension(cme);
}
public static void Detach()
{
Application.RemoveDefaultContextMenuExtension(cme);
}
private static void On1st(Object o, EventArgs e)
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("\nFirst item selected.");
Utils.PostCommandPrompt();
}
private static void On2nd(Object o, EventArgs e)
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("\nSecond item selected.");
Utils.PostCommandPrompt();
}
private static void On3rd(Object o, EventArgs e)
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("\nThird item selected.");
Utils.PostCommandPrompt();
}
}
}
And here are our custom menu items on AutoCAD's default context menu: