コード例 #1
0
 public static extern bool InsertMenuItem(
     IntPtr hMenu,
     uint uItem,
     [MarshalAs(UnmanagedType.Bool)] bool fByPosition,
     ref MENUITEMINFO mii);
コード例 #2
0
        /// <summary>
        /// Add commands to a shortcut menu.
        /// </summary>
        /// <param name="hMenu">A handle to the shortcut menu.</param>
        /// <param name="iMenu">The zero-based position at which to insert the first new menu item.</param>
        /// <param name="idCmdFirst">The minimum value that the handler can specify for a menu item ID.</param>
        /// <param name="idCmdLast">The maximum value that the handler can specify for a menu item ID.</param>
        /// <param name="uFlags">Optional flags that specify how the shortcut menu can be changed.</param>
        /// <returns>
        /// If successful, returns an HRESULT value that has its severity value set
        /// to SEVERITY_SUCCESS and its code value set to the offset of the largest
        /// command identifier that was assigned, plus one.
        /// </returns>
        public int QueryContextMenu(IntPtr hMenu, uint iMenu, uint idCmdFirst, uint idCmdLast, uint uFlags)
        {
            // If uFlags include CMF_DEFAULTONLY then we should not do anything.
            if (((uint)CMF.CMF_DEFAULTONLY & uFlags) != 0)
            {
                return(NativeHelpers.MakeHResult(WinError.SEVERITY_SUCCESS, 0, 0));
            }

            // Check if the user wants to see the extended context menu (i.e. pressing Shift while opening the context menu).
            this.isExtendedContextMenu = ((uint)CMF.CMF_EXTENDEDVERBS & uFlags) != 0;

            this.activeCommands.Clear();
            var maxItems = (idCmdLast - idCmdFirst) + 1 - 2 /* Subtract 2 for the separators */;

            if (maxItems > 0)
            {
                var menuIndex = iMenu;

                // Add a separator.
                var beginSeparator = new MENUITEMINFO();
                beginSeparator.cbSize = (uint)Marshal.SizeOf(beginSeparator);
                beginSeparator.fMask  = MIIM.MIIM_TYPE;
                beginSeparator.fType  = MFT.MFT_SEPARATOR;
                if (!NativeMethods.InsertMenuItem(hMenu, menuIndex++, true, ref beginSeparator))
                {
                    return(Marshal.GetHRForLastWin32Error());
                }

                // Add the commands.
                var context       = new CommandContext(this.selectedShellItems, this.isExtendedContextMenu);
                var commandOffset = default(uint);
                foreach (var command in CommandFactory.GetAvailableCommands())
                {
                    try
                    {
                        var commandState = command.GetState(context);
                        if (commandState != null && commandState.IsVisible)
                        {
                            var verb          = Guid.NewGuid().ToString(); // Create a unique verb to be able to retrieve the right command later on based on that verb.
                            var activeCommand = new ActiveCommand(command, verb, commandOffset++);
                            this.activeCommands.Add(activeCommand);

                            var mii = new MENUITEMINFO();
                            mii.cbSize     = (uint)Marshal.SizeOf(mii);
                            mii.fMask      = MIIM.MIIM_BITMAP | MIIM.MIIM_STRING | MIIM.MIIM_FTYPE | MIIM.MIIM_ID | MIIM.MIIM_STATE;
                            mii.wID        = idCmdFirst + activeCommand.Offset;
                            mii.fType      = MFT.MFT_STRING;
                            mii.dwTypeData = commandState.MenuText;

                            if (!commandState.IsEnabled)
                            {
                                mii.fState = MFS.MFS_DISABLED;
                            }
                            else if (commandState.IsChecked)
                            {
                                mii.fState = MFS.MFS_CHECKED;
                            }
                            else
                            {
                                mii.fState = MFS.MFS_ENABLED;
                            }

                            if (!NativeMethods.InsertMenuItem(hMenu, menuIndex++, true, ref mii))
                            {
                                return(Marshal.GetHRForLastWin32Error());
                            }

                            if (this.activeCommands.Count >= maxItems)
                            {
                                break;
                            }
                        }
                    }
                    catch (Exception exc)
                    {
                        Logger.LogError($"Error querying command \"{command.Name}\": {exc.ToString()}");
                    }
                }

                // Add a separator.
                var endSeparator = new MENUITEMINFO();
                endSeparator.cbSize = (uint)Marshal.SizeOf(endSeparator);
                endSeparator.fMask  = MIIM.MIIM_TYPE;
                endSeparator.fType  = MFT.MFT_SEPARATOR;
                if (!NativeMethods.InsertMenuItem(hMenu, menuIndex++, true, ref endSeparator))
                {
                    return(Marshal.GetHRForLastWin32Error());
                }
            }

            // Return an HRESULT value with the severity set to SEVERITY_SUCCESS.
            // Set the code value to the offset of the largest command identifier
            // that was assigned, plus one (1).
            return(NativeHelpers.MakeHResult(WinError.SEVERITY_SUCCESS, 0, (uint)this.activeCommands.Count));
        }