It's been quite a week - between interviews for a DevTech position we're working to fill in Beijing and AU proposals (my team managed to pull together and submit nearly 60 API class proposals at the beginning of the week) life has been extremely hectic.
Thankfully we're now in the middle of the "May Day Golden Week" here in China. The Chinese government schedules three Golden Weeks every year - one for Spring Festival, one for Labour Day (also known as May Day) and one for the National Day. They're basically week-long holidays formed by a few standard holidays and mandating that people work through an adjacent weekend, grouping together the holidays with the days that are freed up into a contiguous week-long break. These weeks are designed to promote domestic tourism, by allowing people to plan vacations well in advance, and they seem to be working, apparently 25% of domestic tourism in China is due to these three Golden Weeks.
Anyway - I've been working, on and off, as my team isn't all based in China, but I did get to spend some quality time with my family. All this to say it's been a week since my last post, so I'm up late on Friday night to assuage my guilt. :-)
I threw some simple code together to show how to add your own custom context menu to a particular type of AutoCAD object using .NET. The below code adds a new context menu at the "Entity" level, which means that as long as only entities are selected in the editor, the context menu will appear. As objects have to be of type Entity to be selectable, I think it's safe to say the context menu will always be accessible. :-)
You could very easily modify the code to only show the menu for a concrete class of object (Lines, Circles, etc.), of course.
So what does this new context menu do? In this case it simply fires off a command, which then selects our entities by accessing the pickfirst selection set, and does something with the selected entities. The actual command I implemented was very simple, indeed: it simply counts the entities selected and writes a message to the command-line.
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 System;
namespace ContextMenuApplication
{
public class Commands : IExtensionApplication
{
public void Initialize()
{
CountMenu.Attach();
}
public void Terminate()
{
CountMenu.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()
{
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);
}
}
}
And here's what we see when we have our application loaded, right-clicking after selecting some AutoCAD objects:
Followed by the somewhat mundane result:
Selected 10 entities.


Subscribe via RSS
Great!
Is this possible through ObjectARX C++ too?
Regards.
Posted by: Fernando Malard | May 04, 2007 at 07:36 PM
Hi Fernando,
Sure - if you grep the ObjectARX samples folder for "acedAddObjectContextMenu", you'll find a few samples demonstrating this feature (CurveText, SubEntity & contextmenu).
Regards,
Kean
Posted by: Kean | May 05, 2007 at 01:28 AM
I noticed that after I call 'PromptSelectionResult psr = ed.GetSelection()' my selection is reset. Is there a way to leave the current selection unchanged?
I played a bit with 'PromptSelectionOptions' but... nothing! ):
TIA,
Cabbi
Posted by: Cabbi | May 24, 2007 at 01:54 PM
The technique in this post should help.
Kean
Posted by: Kean | May 25, 2007 at 04:20 AM
Hey there. My question is: Can we insert a command in the LAYOUT(sheet) context menu ( in C++) ? And can that command be executed without clearing the layout selection?
10x,
gabriel
Posted by: Gabriel | May 29, 2007 at 02:55 PM
Hi Gabriel,
Sorry - I'm not aware of any way to do this.
Regards,
Kean
Posted by: Kean | May 30, 2007 at 03:51 AM
I converted the code to Vb.net. It compiled well, but did not add context menu on right click... What can be the reason??
Best regards,
Sajjad
Here is the code:
Namespace ContextMenuApplication
Public Class Commands
Implements IExtensionApplication
Public Sub Initialize() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Initialize
CountMenu.Attach()
End Sub
Public Sub Terminate() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Terminate
CountMenu.Detach()
End Sub
Public Sub CountSelection()
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim psr As PromptSelectionResult = ed.GetSelection()
If (psr.Status = PromptStatus.OK) Then
ed.WriteMessage("\nSelected {0} entities.", psr.Value.Count())
End If
End Sub
End Class
Public Class CountMenu
Private Shared cme As ContextMenuExtension
Public Shared Sub Attach()
cme = New ContextMenuExtension
Dim mi As MenuItem = New MenuItem("Count")
AddHandler mi.Click, AddressOf OnCount
cme.MenuItems.Add(mi)
Dim rxc As RXClass = Entity.GetClass(GetType(Entity))
Application.AddObjectContextMenuExtension(rxc, cme)
End Sub
Public Shared Sub Detach()
Dim rxc As RXClass = Entity.GetClass(GetType(Entity))
Application.RemoveObjectContextMenuExtension(rxc, cme)
End Sub
Private Shared Sub OnCount(ByVal o As Object, ByVal e As EventArgs)
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
doc.SendStringToExecute("_.COUNT ", True, False, False)
End Sub
End Class
End Namespace
Posted by: Sajjad | November 05, 2007 at 11:44 PM
Sajjad,
It works for me. What type of entity are you clicking on to get the menu to appear?
If you're just right-clicking on the drawing (not an entity) then you won't get the menu item - it's registered against the Entity class.
Kean
Posted by: Kean | November 07, 2007 at 02:14 PM
I learned that if system variable PICKFIRST=0 then custom context menu does not show up. I set it to 1 and it worked.
Sajjad
Posted by: Sajjad | November 08, 2007 at 08:39 PM
all this discussion helped me a lot.
can you please provide a code snippet to display the short cut menu corresponding the selected entity using autocad vba
Posted by: SUBIR KUMAR DUTTA | April 11, 2008 at 03:15 PM
Hi,
It's Possible to have the new context menu without select a object ?
Posted by: Thib | April 25, 2008 at 01:44 PM
Hi Thib,
Yes - see this post.
Kean
Posted by: Kean | April 25, 2008 at 02:31 PM
Hi Kean,
Can we add or remove the contextmenu in runtime, I'm working with entities that have special xrecords, my contextmenu should appear depending on what's in the xrecord?
Do you see a way to achieve this?
Thanks
Kristof
Posted by: Kristof | April 30, 2008 at 04:19 PM
Hi Kristof,
Sorry - I don't see how that's possible with the existing mechanism.
Regards,
Kean
Posted by: Kean | April 30, 2008 at 04:51 PM
"Can we add or remove the contextmenu in runtime?" - What about using Popup event of myContextMenuExtension object?
Posted by: li | July 09, 2008 at 01:08 PM
I'm actually thinking about making this a subject of a post. You should be able to use one of these COM (not .NET) events from the Document object:
BeginShortcutMenuCommand event
Triggered after the user right-clicks on the drawing window, and before the shortcut menu appears in command mode.
BeginShortcutMenuDefault event
Triggered after the user right-clicks on the drawing window, and before the shortcut menu appears in default mode.
BeginShortcutMenuEdit event
Triggered after the user right-clicks on the drawing window, and before the shortcut menu appears in edit mode.
BeginShortcutMenuGrip event
Triggered after the user right-clicks on the drawing window, and before the shortcut menu appears in grip mode.
BeginShortcutMenuOSnap event
Triggered after the user right-clicks on the drawing window, and before the shortcut menu appears in osnap mode.
Kean
Posted by: Kean | July 09, 2008 at 01:41 PM
Hi Kean,
What about using Popup event of ContextMenuExtension object in .NET?
Test my code.
public class CountMenu
{
private static ContextMenuExtension cme;
public static void Attach()
{
cme = new ContextMenuExtension();
cme.Popup += new EventHandler(OnPopup);
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);
}
private static void OnPopup(Object o, EventArgs e)
{
cme.MenuItems.Clear();
if (Analyse Something)
{
MenuItem mi = new MenuItem("Count");
mi.Click += new EventHandler(OnCount);
cme.MenuItems.Add(mi);
}
}
}
}
That`s all :)
Posted by: al | July 10, 2008 at 06:21 AM
That seems to work very well - thanks, al!
Kean
Posted by: Kean | July 10, 2008 at 01:01 PM