Support
Joined: 18 Jul 2005 Posts: 731
|
Posted: Mon Oct 06, 2008 2:48 pm Post subject: HOWTO: Add large number of menu items (beyond the number of menu item slots provided by Windows) |
|
|
Windows reserves a specific number of menu item IDs for each context menu extension. This limit is generally at least 100. The exact number can be determined in the GetMenuItems method using e.MaxMenuItemsAvailable (GetMenuitemsEventArgs.MaxMenuItemsAvailable ). This limit is sufficient for most purposes, but if you need to add a large number of menu items (including all items in sub-menus and sub-sub-menus), you must reuse the same IDs for menu items in different sub-menus (reasonably assuming that your large number of items are spread across more than one sub-menu). The following code demonstrates how to achieve that :
[C#]
Code: | int startID; // start ID available for our use
ShellMenuItem lastpopupMenuItem = null; // last sub menu which popped
protected override void OnGetMenuItems(LogicNP.EZShellExtensions.GetMenuitemsEventArgs e)
{
// Add main menus
ShellMenuItem mi1 = e.Menu.AddItem("MenuItem1");
mi1.Tag = 1; // level 1
ShellMenuItem mi2 = e.Menu.AddItem("MenuItem2");
mi2.Tag = 1; // level 1
ShellMenuItem mi3 = e.Menu.AddItem("MenuItem3");
mi3.Tag = 1; // level 1
mi1.HasSubMenu = true; // Indicate menu has submenu
// Store the ID of the 'dummy menu item.
// All dummy menu items will have this ID
// All actual menu items will have IDs starting from startID to startID+49 (total 50 items)
startID = mi1.SubMenu.AddItem("dummy").ID; // Add a dummy item to submenu **necessary
mi2.HasSubMenu = true; // Indicate menu has submenu
mi2.SubMenu.AddItem("dummy",startID); // Add a dummy item to submenu **necessary
mi3.HasSubMenu = true; // Indicate menu has submenu
mi3.SubMenu.AddItem("dummy",startID); // Add a dummy item to submenu **necessary
// Each submenu of mi1,mi2 and mi3 can have maximum of 50 submenu items, so reserve space for
// 49 more (1 ID for the 'dummy' item already added which will be removed as each submenu pops up)
e.ReservedMenuItemCount=49;
}
protected override void OnPopupSubMenu(ShellMenuItem menuItem)
{
// New menu items are at current level + 1
int level = (int)menuItem.Tag + 1;
lastpopupMenuItem = menuItem; // store the last menu which popped up
menuItem.SubMenu.RemoveAll(); // remove 'dummy' item
// Add the 50 menu items
for (int i = 0; i < 50;i++)
{
// Explicitly specify id for the menu item.
ShellMenuItem item = menuItem.SubMenu.AddItem(menuItem.Caption + "_subMenuItem" + i.ToString(), startID + i);
// We will limit sub-menus to 2 levels
if (level<=2)
{
item.HasSubMenu = true;
item.SubMenu.AddItem("dummy", startID);
item.Tag = level + 1;
}
}
}
protected override bool OnExecuteMenuItem(LogicNP.EZShellExtensions.ExecuteItemEventArgs e)
{
// e,MenuItem is not the correct menu item because we have used duplicate ids which confuses Windows.
// The real menu item which has been clicked is the one with the same ID as e.MenuItem.ID but which is
// a sub menu item of 'lastpopupMenuItem'
ShellMenuItem real = lastpopupMenuItem.SubMenu.GetItemFromID(e.MenuItem.ID);
MessageBox.Show(real.Caption);
return true;
} |
[VB.Net]
Code: | Dim startID As Integer ' start ID available for our use
Dim lastpopupMenuItem As ShellMenuItem = Nothing ' last sub menu which popped
' Override this method to add your menu items to the context menu
Protected Overrides Sub OnGetMenuItems(ByVal e As LogicNP.EZShellExtensions.GetMenuitemsEventArgs)
' Add main menus
Dim mi1 As ShellMenuItem = e.Menu.AddItem("MenuItem1")
mi1.Tag = 1 ' level 1
Dim mi2 As ShellMenuItem = e.Menu.AddItem("MenuItem2")
mi2.Tag = 1 ' level 1
Dim mi3 As ShellMenuItem = e.Menu.AddItem("MenuItem3")
mi3.Tag = 1 ' level 1
mi1.HasSubMenu = True ' Indicate menu has submenu
' Store the ID of the dummy menu item.
' All dummy menu items will have this ID
' All actual menu items will have IDs starting from startID to startID+49 (total 50 items)
startID = mi1.SubMenu.AddItem("dummy").ID ' Add a dummy item to submenu **necessary
mi2.HasSubMenu = True ' Indicate menu has submenu
mi2.SubMenu.AddItem("dummy", startID) ' Add a dummy item to submenu **necessary
mi3.HasSubMenu = True ' Indicate menu has submenu
mi3.SubMenu.AddItem("dummy", startID) ' Add a dummy item to submenu **necessary
' Each submenu of mi1,mi2 and mi3 can have maximum of 50 submenu items, so reserve space for
' 49 more (1 ID for the 'dummy' item already added which will be removed as each submenu pops up)
e.ReservedMenuItemCount = 49
End Sub
Protected Overrides Sub OnPopupSubMenu(ByVal menuItem As ShellMenuItem)
' New menu items are at current level + 1
Dim level As Integer = CType(menuItem.Tag + 1, Integer)
lastpopupMenuItem = menuItem ' store the last menu which popped up
menuItem.SubMenu.RemoveAll() ' remove 'dummy' item
Dim i As Integer
' Add the 50 menu items
For i = 0 To 49
' Explicitly specify id for the menu item.
Dim item As ShellMenuItem = menuItem.SubMenu.AddItem(menuItem.Caption + "_subMenuItem" + i.ToString(), startID + i)
' We will limit sub-menus to 2 levels
If (level <= 2) Then
item.HasSubMenu = True
item.SubMenu.AddItem("dummy", startID)
item.Tag = level + 1
End If
Next i
End Sub
' Override this method to perform your own tasks when any of the
' menu items provided by your contextmenu extension is selected by the user.
Protected Overrides Function OnExecuteMenuItem(ByVal e As LogicNP.EZShellExtensions.ExecuteItemEventArgs) As Boolean
' e,MenuItem is not the correct menu item because we have used duplicate ids which confuses Windows.
' The real menu item which has been clicked is the one with the same ID as e.MenuItem.ID but which is
' a sub menu item of 'lastpopupMenuItem'
Dim real As ShellMenuItem = lastpopupMenuItem.SubMenu.GetItemFromID(e.MenuItem.ID)
MessageBox.Show(real.Caption)
Return True
End Function |
|
|