public string Popup(FileSystemInfoEx[] items, Point pt) { if (items.Length > 0 && !_contextMenuVisible) { //0.15: Fixed ShellFolder not freed correctly. using (ShellFolder2 parentShellFolder = items[0].Parent != null ? items[0].Parent.ShellFolder : DirectoryInfoEx.DesktopDirectory.ShellFolder) try { _contextMenuVisible = true; ///Debug.WriteLine(items[0].Parent.FullName); IntPtr ptrContextMenu = IntPtr.Zero; IntPtr ptrContextMenu2 = IntPtr.Zero; IntPtr PtrContextMenu3 = IntPtr.Zero; IntPtr contextMenu = IntPtr.Zero; List <IntPtr> menuPtrConstructed = new List <IntPtr>(); PIDL[] pidls = IOTools.GetPIDL(items, true); if (ContextMenuHelper.GetIContextMenu(parentShellFolder, IOTools.GetPIDLPtr(pidls), out ptrContextMenu, out _iContextMenu)) { try { queryMenuItemsEventArgs = new QueryMenuItemsEventArgs(items); if (OnQueryMenuItems != null) { OnQueryMenuItems(this, queryMenuItemsEventArgs); } contextMenu = ShellAPI.CreatePopupMenu(); if (queryMenuItemsEventArgs.QueryContextMenu) { _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)); } #region obsolute //for (uint i = 0; i < queryMenuItemsEventArgs.ExtraMenuItems.Length; i++) //{ // string caption = queryMenuItemsEventArgs.ExtraMenuItems[i]; // if (caption != "---") // { // ShellAPI.InsertMenu(contextMenu, i, ShellAPI.MFT.BYPOSITION, // ShellAPI.CMD_LAST + i + 1, caption); // if (queryMenuItemsEventArgs.DefaultItem == i) // ShellAPI.SetMenuDefaultItem(contextMenu, i, true); // } // else ShellAPI.InsertMenu(contextMenu, i, ShellAPI.MFT.BYPOSITION | // ShellAPI.MFT.SEPARATOR, 0, "-"); //} #endregion //0.11: Added ContextMenuWrapper OnQueryMenuItems event now support multilevel directory. (e.g. @"Tools\Add") ContextMenuHelperEx.ConstructCustomMenu(contextMenu, queryMenuItemsEventArgs.ExtraMenuItems, out menuPtrConstructed); if (queryMenuItemsEventArgs.QueryContextMenu2) { try { Marshal.QueryInterface(ptrContextMenu, ref ShellAPI.IID_IContextMenu2, out ptrContextMenu2); _iContextMenu2 = (IContextMenu2)Marshal.GetTypedObjectForIUnknown( ptrContextMenu2, typeof(IContextMenu2)); } catch (Exception) { } } if (queryMenuItemsEventArgs.QueryContextMenu3) { try { Marshal.QueryInterface(ptrContextMenu, ref ShellAPI.IID_IContextMenu3, out PtrContextMenu3); _iContextMenu3 = (IContextMenu3)Marshal.GetTypedObjectForIUnknown( PtrContextMenu3, typeof(IContextMenu3)); } catch (Exception) { } } uint GMDI_USEDISABLED = 0x0001; uint GMDI_GOINTOPOPUPS = 0x0002; uint intDefaultItem = (uint)ShellAPI.GetMenuDefaultItem(contextMenu, false, GMDI_USEDISABLED); string strDefaultCommand = intDefaultItem >= ShellAPI.CMD_FIRST ? ContextMenuHelper.GetCommandString(_iContextMenu, intDefaultItem - ShellAPI.CMD_FIRST, true) : null; if (queryMenuItemsEventArgs.QueryContextMenu) //No need to Disable if query is not carried out in first place. { //0.11: Added queryMenuItemsEventArgs.GrayedItems / HiddenItems ContextMenuHelperEx.DisableMenuItems(contextMenu, _iContextMenu, queryMenuItemsEventArgs.GrayedItems, ContextMenuHelperEx.DisabledMethods.Gray); ContextMenuHelperEx.DisableMenuItems(contextMenu, _iContextMenu, queryMenuItemsEventArgs.HiddenItems, ContextMenuHelperEx.DisabledMethods.Remove); } //0.17: Added DefaultItem and DefaultCommand in BeforePopup bool cont = true; if (OnBeforePopup != null) { BeforePopupEventArgs args = new BeforePopupEventArgs (contextMenu, _iContextMenu, intDefaultItem - ShellAPI.CMD_FIRST, strDefaultCommand); OnBeforePopup(this, args); cont = args.ContinuePopup; } if (cont) { //0.18 Fixed Context menu disappear in some case. (By cwharmon) //http://www.codeproject.com/KB/files/DirectoryInfoEx.aspx#xx3475961xx ShellAPI.SetForegroundWindow(this.Handle); uint selected = ShellAPI.TrackPopupMenuEx(contextMenu, ShellAPI.TPM.RETURNCMD, pt.X, pt.Y, this.Handle, IntPtr.Zero); uint msg = 0; ShellAPI.PostMessage(this.Handle, msg, IntPtr.Zero, IntPtr.Zero); if (OnMouseHover != null) { OnMouseHover(this, new MouseHoverEventArgs("", "", 0)); } if (selected > ShellAPI.CMD_LAST) { return(removeCheckedSymbol(queryMenuItemsEventArgs.ExtraMenuItems[selected - ShellAPI.CMD_LAST - 1])); } if (selected >= ShellAPI.CMD_FIRST) { string command = ContextMenuHelper.GetCommandString(_iContextMenu, selected - ShellAPI.CMD_FIRST, true); if (command == null) { return(null); } if (OnBeforeInvokeCommand != null) { InvokeCommandEventArgs args = new InvokeCommandEventArgs(command, "", selected, items); OnBeforeInvokeCommand(this, args); if (!args.ContinueInvoke) { return(command); } } if (command == "rename") { return("rename"); } else { //if (items.Length == 1 && items[0] is DirectoryInfoEx) ContextMenuHelper.InvokeCommand(_iContextMenu, selected - ShellAPI.CMD_FIRST, (items[0].Parent != null) ? items[0].Parent.FullName : items[0].FullName, pt); //else //ContextMenuHelper.InvokeCommand(items[0].Parent, // IOTools.GetPIDLPtr(items, true), selected - ShellAPI.CMD_FIRST, // pt); } } } } finally { IOTools.FreePIDL(pidls); if (_iContextMenu != null) { Marshal.ReleaseComObject(_iContextMenu); _iContextMenu = null; } if (_iContextMenu2 != null) { Marshal.ReleaseComObject(_iContextMenu2); _iContextMenu2 = null; } if (_iContextMenu3 != null) { Marshal.ReleaseComObject(_iContextMenu3); _iContextMenu3 = null; } foreach (IntPtr menuPtr in menuPtrConstructed) { ShellAPI.DestroyMenu(menuPtr); } menuPtrConstructed.Clear(); if (contextMenu != null) { ShellAPI.DestroyMenu(contextMenu); } if (ptrContextMenu != IntPtr.Zero) { Marshal.Release(ptrContextMenu); } if (ptrContextMenu2 != IntPtr.Zero) { Marshal.Release(ptrContextMenu2); } if (PtrContextMenu3 != IntPtr.Zero) { Marshal.Release(PtrContextMenu3); } } } } finally { if (OnAfterPopup != null) { AfterPopupEventArgs args = new AfterPopupEventArgs(); OnAfterPopup(this, args); } _contextMenuVisible = false; } } return(null); }
public string Popup(FileSystemInfoEx[] items, Point pt) { if (items.Length > 0 && !_contextMenuVisible) { //0.15: Fixed ShellFolder not freed correctly. using (ShellFolder2 parentShellFolder = items[0].Parent != null ? items[0].Parent.ShellFolder : DirectoryInfoEx.DesktopDirectory.ShellFolder) try { _contextMenuVisible = true; ///Debug.WriteLine(items[0].Parent.FullName); IntPtr ptrContextMenu = IntPtr.Zero; IntPtr ptrContextMenu2 = IntPtr.Zero; IntPtr PtrContextMenu3 = IntPtr.Zero; IntPtr contextMenu = IntPtr.Zero; List<IntPtr> menuPtrConstructed = new List<IntPtr>(); PIDL[] pidls = IOTools.GetPIDL(items, true); if (ContextMenuHelper.GetIContextMenu(parentShellFolder, IOTools.GetPIDLPtr(pidls), out ptrContextMenu, out _iContextMenu)) try { queryMenuItemsEventArgs = new QueryMenuItemsEventArgs(items); if (OnQueryMenuItems != null) OnQueryMenuItems(this, queryMenuItemsEventArgs); contextMenu = ShellAPI.CreatePopupMenu(); if (queryMenuItemsEventArgs.QueryContextMenu) _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)); #region obsolute //for (uint i = 0; i < queryMenuItemsEventArgs.ExtraMenuItems.Length; i++) //{ // string caption = queryMenuItemsEventArgs.ExtraMenuItems[i]; // if (caption != "---") // { // ShellAPI.InsertMenu(contextMenu, i, ShellAPI.MFT.BYPOSITION, // ShellAPI.CMD_LAST + i + 1, caption); // if (queryMenuItemsEventArgs.DefaultItem == i) // ShellAPI.SetMenuDefaultItem(contextMenu, i, true); // } // else ShellAPI.InsertMenu(contextMenu, i, ShellAPI.MFT.BYPOSITION | // ShellAPI.MFT.SEPARATOR, 0, "-"); //} #endregion //0.11: Added ContextMenuWrapper OnQueryMenuItems event now support multilevel directory. (e.g. @"Tools\Add") ContextMenuHelperEx.ConstructCustomMenu(contextMenu, queryMenuItemsEventArgs.ExtraMenuItems, out menuPtrConstructed); if (queryMenuItemsEventArgs.QueryContextMenu2) try { Marshal.QueryInterface(ptrContextMenu, ref ShellAPI.IID_IContextMenu2, out ptrContextMenu2); _iContextMenu2 = (IContextMenu2)Marshal.GetTypedObjectForIUnknown( ptrContextMenu2, typeof(IContextMenu2)); } catch (Exception) { } if (queryMenuItemsEventArgs.QueryContextMenu3) try { Marshal.QueryInterface(ptrContextMenu, ref ShellAPI.IID_IContextMenu3, out PtrContextMenu3); _iContextMenu3 = (IContextMenu3)Marshal.GetTypedObjectForIUnknown( PtrContextMenu3, typeof(IContextMenu3)); } catch (Exception) { } uint GMDI_USEDISABLED = 0x0001; uint GMDI_GOINTOPOPUPS = 0x0002; uint intDefaultItem = (uint)ShellAPI.GetMenuDefaultItem(contextMenu, false, GMDI_USEDISABLED); string strDefaultCommand = intDefaultItem >= ShellAPI.CMD_FIRST ? ContextMenuHelper.GetCommandString(_iContextMenu, intDefaultItem - ShellAPI.CMD_FIRST, true) : null; if (queryMenuItemsEventArgs.QueryContextMenu) //No need to Disable if query is not carried out in first place. { //0.11: Added queryMenuItemsEventArgs.GrayedItems / HiddenItems ContextMenuHelperEx.DisableMenuItems(contextMenu, _iContextMenu, queryMenuItemsEventArgs.GrayedItems, ContextMenuHelperEx.DisabledMethods.Gray); ContextMenuHelperEx.DisableMenuItems(contextMenu, _iContextMenu, queryMenuItemsEventArgs.HiddenItems, ContextMenuHelperEx.DisabledMethods.Remove); } //0.17: Added DefaultItem and DefaultCommand in BeforePopup bool cont = true; if (OnBeforePopup != null) { BeforePopupEventArgs args = new BeforePopupEventArgs (contextMenu, _iContextMenu, intDefaultItem - ShellAPI.CMD_FIRST, strDefaultCommand); OnBeforePopup(this, args); cont = args.ContinuePopup; } if (cont) { //0.18 Fixed Context menu disappear in some case. (By cwharmon) //http://www.codeproject.com/KB/files/DirectoryInfoEx.aspx#xx3475961xx ShellAPI.SetForegroundWindow(this.Handle); uint selected = ShellAPI.TrackPopupMenuEx(contextMenu, ShellAPI.TPM.RETURNCMD, pt.X, pt.Y, this.Handle, IntPtr.Zero); uint msg = 0; ShellAPI.PostMessage(this.Handle, msg, IntPtr.Zero, IntPtr.Zero); if (OnMouseHover != null) OnMouseHover(this, new MouseHoverEventArgs("", "", 0)); if (selected > ShellAPI.CMD_LAST) { return removeCheckedSymbol(queryMenuItemsEventArgs.ExtraMenuItems[selected - ShellAPI.CMD_LAST - 1]); } if (selected >= ShellAPI.CMD_FIRST) { string command = ContextMenuHelper.GetCommandString(_iContextMenu, selected - ShellAPI.CMD_FIRST, true); if (command == null) return null; if (OnBeforeInvokeCommand != null) { InvokeCommandEventArgs args = new InvokeCommandEventArgs(command, "", selected, items); OnBeforeInvokeCommand(this, args); if (!args.ContinueInvoke) return command; } if (command == "rename") return "rename"; else { //if (items.Length == 1 && items[0] is DirectoryInfoEx) ContextMenuHelper.InvokeCommand(_iContextMenu, selected - ShellAPI.CMD_FIRST, (items[0].Parent != null) ? items[0].Parent.FullName : items[0].FullName, pt); //else //ContextMenuHelper.InvokeCommand(items[0].Parent, // IOTools.GetPIDLPtr(items, true), selected - ShellAPI.CMD_FIRST, // pt); } } } } finally { IOTools.FreePIDL(pidls); if (_iContextMenu != null) { Marshal.ReleaseComObject(_iContextMenu); _iContextMenu = null; } if (_iContextMenu2 != null) { Marshal.ReleaseComObject(_iContextMenu2); _iContextMenu2 = null; } if (_iContextMenu3 != null) { Marshal.ReleaseComObject(_iContextMenu3); _iContextMenu3 = null; } foreach (IntPtr menuPtr in menuPtrConstructed) ShellAPI.DestroyMenu(menuPtr); menuPtrConstructed.Clear(); if (contextMenu != null) ShellAPI.DestroyMenu(contextMenu); if (ptrContextMenu != IntPtr.Zero) Marshal.Release(ptrContextMenu); if (ptrContextMenu2 != IntPtr.Zero) Marshal.Release(ptrContextMenu2); if (PtrContextMenu3 != IntPtr.Zero) Marshal.Release(PtrContextMenu3); } } finally { if (OnAfterPopup != null) { AfterPopupEventArgs args = new AfterPopupEventArgs(); OnAfterPopup(this, args); } _contextMenuVisible = false; } } return null; }