private static string GetCommandString(Shell32.IContextMenu cMenu, uint offset, Shell32.GCS flags = Shell32.GCS.GCS_VERBW) { if (offset > 5000) { // Hackish workaround to avoid an AccessViolationException on some items, // notably the "Run with graphic processor" menu item of NVidia cards return(null); } SafeCoTaskMemString commandString = null; try { commandString = new SafeCoTaskMemString(512); cMenu.GetCommandString(new IntPtr(offset), flags, IntPtr.Zero, commandString, (uint)commandString.Capacity - 1); Debug.WriteLine("Verb {0}: {1}", offset, commandString); return(commandString.ToString()); } catch (Exception ex) when(ex is InvalidCastException || ex is ArgumentException) { // TODO: investigate this.. Debug.WriteLine(ex); return(null); } catch (Exception ex) when(ex is COMException || ex is NotImplementedException) { // Not every item has an associated verb return(null); } finally { commandString?.Dispose(); } }
private static string GetCommandString(Shell32.IContextMenu cMenu, uint offset, Shell32.GCS flags = Shell32.GCS.GCS_VERBW) { SafeCoTaskMemString commandString = null; try { commandString = new SafeCoTaskMemString(512); cMenu.GetCommandString(new IntPtr(offset), flags, IntPtr.Zero, commandString, (uint)commandString.Capacity - 1); Debug.WriteLine("Verb {0}: {1}", offset, commandString); return(commandString.ToString()); } catch (Exception ex) when(ex is InvalidCastException || ex is ArgumentException) { // TODO: investigate this.. Debug.WriteLine(ex); return(null); } catch (Exception ex) when(ex is COMException || ex is NotImplementedException) { // Not every item has an associated verb return(null); } finally { commandString?.Dispose(); } }
public void SafeResourceIdTest3() { const string s = "Test"; var sptr = new SafeCoTaskMemString(s); var r = new SafeResourceId((IntPtr)sptr); sptr.Dispose(); Assert.That(r.IsInvalid, Is.False); Assert.That(r.ToString(), Is.EqualTo(s)); Assert.That((string)r, Is.EqualTo(s)); Assert.That((int)r, Is.EqualTo(0)); const int i = 5; r = (IntPtr)i; Assert.That(r.Equals((IntPtr)i)); Assert.That(r.IsInvalid, Is.False); Assert.That(r.ToString(), Does.StartWith("#")); Assert.That((string)r, Does.StartWith("#")); Assert.That((int)r, Is.EqualTo(i)); Assert.That(((IntPtr)r).ToInt32(), Is.EqualTo(i)); }
private static void EnumMenuItems( Shell32.IContextMenu cMenu, HMENU hMenu, List <Win32ContextMenuItem> menuItemsResult, Func <string, bool> itemFilter = null) { var itemCount = User32.GetMenuItemCount(hMenu); var mii = new User32.MENUITEMINFO(); mii.cbSize = (uint)Marshal.SizeOf(mii); mii.fMask = User32.MenuItemInfoMask.MIIM_BITMAP | User32.MenuItemInfoMask.MIIM_FTYPE | User32.MenuItemInfoMask.MIIM_STRING | User32.MenuItemInfoMask.MIIM_ID | User32.MenuItemInfoMask.MIIM_SUBMENU; for (uint ii = 0; ii < itemCount; ii++) { var menuItem = new ContextMenuItem(); var container = new SafeCoTaskMemString(512); mii.dwTypeData = (IntPtr)container; mii.cch = (uint)container.Capacity - 1; // https://devblogs.microsoft.com/oldnewthing/20040928-00/?p=37723 var retval = User32.GetMenuItemInfo(hMenu, ii, true, ref mii); if (!retval) { container.Dispose(); continue; } menuItem.Type = (MenuItemType)mii.fType; menuItem.ID = (int)(mii.wID - 1); // wID - idCmdFirst if (menuItem.Type == MenuItemType.MFT_STRING) { Debug.WriteLine("Item {0} ({1}): {2}", ii, mii.wID, mii.dwTypeData); menuItem.Label = mii.dwTypeData; menuItem.CommandString = GetCommandString(cMenu, mii.wID - 1); if (itemFilter != null && (itemFilter(menuItem.CommandString) || itemFilter(menuItem.Label))) { // Skip items implemented in UWP container.Dispose(); continue; } if (mii.hbmpItem != HBITMAP.NULL && !Enum.IsDefined(typeof(HBITMAP_HMENU), ((IntPtr)mii.hbmpItem).ToInt64())) { var bitmap = GetBitmapFromHBitmap(mii.hbmpItem); if (bitmap != null) { menuItem.Icon = bitmap; } } if (mii.hSubMenu != HMENU.NULL) { Debug.WriteLine("Item {0}: has submenu", ii); var subItems = new List <Win32ContextMenuItem>(); try { (cMenu as Shell32.IContextMenu2)?.HandleMenuMsg((uint)User32.WindowMessage.WM_INITMENUPOPUP, (IntPtr)mii.hSubMenu, new IntPtr(ii)); } catch (NotImplementedException) { // Only for dynamic/owner drawn? (open with, etc) } EnumMenuItems(cMenu, mii.hSubMenu, subItems, itemFilter); menuItem.SubItems = subItems; Debug.WriteLine("Item {0}: done submenu", ii); } } else { Debug.WriteLine("Item {0}: {1}", ii, mii.fType.ToString()); } container.Dispose(); menuItemsResult.Add(menuItem); } }