internal static void ConstructCustomMenu(IntPtr menu, CustomMenuStructure[] customItems, out List <IntPtr> menuPtrConstructed) { menuPtrConstructed = new List <IntPtr>(); for (int i = 0; i < customItems.Length; i++) { CustomMenuStructure item = customItems[i]; if (item.IsFolder) { IntPtr newPopup = ShellAPI.CreatePopupMenu(); menuPtrConstructed.Add(newPopup); ShellAPI.InsertMenu(menu, (uint)i, ShellAPI.MFT.BYPOSITION | ShellAPI.MFT.POPUP, newPopup, item.Text); List <IntPtr> submenuPtrConstructed; ConstructCustomMenu(newPopup, item.Items.ToArray(), out submenuPtrConstructed); menuPtrConstructed.AddRange(submenuPtrConstructed); } else if (item.Text == "---") { ShellAPI.InsertMenu(menu, (uint)i, ShellAPI.MFT.BYPOSITION | ShellAPI.MFT.SEPARATOR, IntPtr.Zero, ""); } else { ShellAPI.MFT extraFlag = 0; if (item.Checked) { extraFlag |= ShellAPI.MFT.CHECKED; } ShellAPI.InsertMenu(menu, (uint)i, ShellAPI.MFT.BYPOSITION | extraFlag, new UIntPtr(ShellAPI.CMD_LAST + item.ID + 1), item.Text); } } }
public MENUITEMINFO(string text) { this.cbSize = ShellAPI.cbMenuItemInfo; this.dwTypeData = text; this.cch = text.Length; this.fMask = (ShellAPI.MIIM) 0u; this.fType = ShellAPI.MFT.BYCOMMAND; this.fState = ShellAPI.MFS.ENABLED; this.wID = 0u; this.hSubMenu = IntPtr.Zero; this.hbmpChecked = IntPtr.Zero; this.hbmpUnchecked = IntPtr.Zero; this.dwItemData = IntPtr.Zero; this.hbmpItem = IntPtr.Zero; }
public static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, ShellAPI.MFT uFlags);
public static extern bool InsertMenu(IntPtr hmenu, uint uPosition, ShellAPI.MFT uflags, uint uIDNewItem, [MarshalAs(UnmanagedType.LPTStr)] string lpNewItem);
public static extern bool AppendMenu(IntPtr hMenu, ShellAPI.MFT uFlags, uint uIDNewItem, [MarshalAs(UnmanagedType.LPTStr)] string lpNewItem);
/// <summary> /// When the mouse goes up on an node and suspendContextMenu is true, this method will show the /// ContextMenu for that node and after the user selects an item, it will execute that command. /// </summary> void FolderView_MouseUp(object sender, MouseEventArgs e) { if (suspendContextMenu || contextMenuVisible) { suspendContextMenu = false; return; } TreeViewHitTestInfo hitTest = br.FolderView.HitTest(e.Location); contextMenuVisible = true; if (e.Button == MouseButtons.Right && (hitTest.Location == TreeViewHitTestLocations.Image || hitTest.Location == TreeViewHitTestLocations.Label || hitTest.Location == TreeViewHitTestLocations.StateImage)) { #region Fields ShellItem item = (ShellItem)hitTest.Node.Tag; IntPtr contextMenu = IntPtr.Zero, iContextMenuPtr = IntPtr.Zero, iContextMenuPtr2 = IntPtr.Zero, iContextMenuPtr3 = IntPtr.Zero; IShellFolder parentShellFolder = (item.ParentItem != null) ? item.ParentItem.ShellFolder : item.ShellFolder; #endregion #region Show / Invoke try { if (ContextMenuHelper.GetIContextMenu(parentShellFolder, new IntPtr[] { item.PIDLRel.Ptr }, out iContextMenuPtr, out iContextMenu)) { contextMenu = ShellAPI.CreatePopupMenu(); iContextMenu.QueryContextMenu( contextMenu, 0, ShellAPI.CMD_FIRST, ShellAPI.CMD_LAST, ShellAPI.CMF.EXPLORE | ShellAPI.CMF.CANRENAME | ((Control.ModifierKeys & Keys.Shift) != 0 ? ShellAPI.CMF.EXTENDEDVERBS : 0)); string topInvoke = hitTest.Node.IsExpanded ? "Collapse" : "Expand"; ShellAPI.MFT extraFlag = (hitTest.Node.Nodes.Count > 0) ? 0 : ShellAPI.MFT.GRAYED; ShellAPI.InsertMenu(contextMenu, 0, ShellAPI.MFT.BYPOSITION | extraFlag, (int)CMD_CUSTOM.ExpandCollapse, topInvoke); ShellAPI.InsertMenu(contextMenu, 1, ShellAPI.MFT.BYPOSITION | ShellAPI.MFT.SEPARATOR, 0, "-"); ShellAPI.SetMenuDefaultItem( contextMenu, 0, true); Marshal.QueryInterface(iContextMenuPtr, ref ShellAPI.IID_IContextMenu2, out iContextMenuPtr2); Marshal.QueryInterface(iContextMenuPtr, ref ShellAPI.IID_IContextMenu3, out iContextMenuPtr3); try { iContextMenu2 = (IContextMenu2)Marshal.GetTypedObjectForIUnknown(iContextMenuPtr2, typeof(IContextMenu2)); iContextMenu3 = (IContextMenu3)Marshal.GetTypedObjectForIUnknown(iContextMenuPtr3, typeof(IContextMenu3)); } catch (Exception) { } Point ptInvoke = br.FolderView.PointToScreen(e.Location); uint selected = ShellAPI.TrackPopupMenuEx( contextMenu, ShellAPI.TPM.RETURNCMD, ptInvoke.X, ptInvoke.Y, this.Handle, IntPtr.Zero); br.OnContextMenuMouseHover(new ContextMenuMouseHoverEventArgs(string.Empty)); if (selected == (int)CMD_CUSTOM.ExpandCollapse) { if (hitTest.Node.IsExpanded) { hitTest.Node.Collapse(true); } else { hitTest.Node.Expand(); } } else if (selected >= ShellAPI.CMD_FIRST) { string command = ContextMenuHelper.GetCommandString( iContextMenu, selected - ShellAPI.CMD_FIRST, true); if (command == "rename") { br.FolderView.LabelEdit = true; hitTest.Node.BeginEdit(); } else { ContextMenuHelper.InvokeCommand( iContextMenu, selected - ShellAPI.CMD_FIRST, (item.ParentItem != null) ? ShellItem.GetRealPath(item.ParentItem) : ShellItem.GetRealPath(item), ptInvoke); } } } } #endregion catch (Exception) { } #region Finally finally { if (iContextMenu != null) { Marshal.ReleaseComObject(iContextMenu); iContextMenu = null; } if (iContextMenu2 != null) { Marshal.ReleaseComObject(iContextMenu2); iContextMenu2 = null; } if (iContextMenu3 != null) { Marshal.ReleaseComObject(iContextMenu3); iContextMenu3 = null; } if (contextMenu != null) { ShellAPI.DestroyMenu(contextMenu); } if (iContextMenuPtr != IntPtr.Zero) { Marshal.Release(iContextMenuPtr); } if (iContextMenuPtr2 != IntPtr.Zero) { Marshal.Release(iContextMenuPtr2); } if (iContextMenuPtr3 != IntPtr.Zero) { Marshal.Release(iContextMenuPtr3); } } #endregion } contextMenuVisible = false; }