Пример #1
0
            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();
                }
            }
Пример #2
0
            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();
                }
            }
Пример #3
0
        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));
        }
Пример #4
0
            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);
                }
            }