public void AddSubMenu(ShellFolder folder, int position, ref IntPtr parentNativeMenuPtr)
        {
            if (GetNewContextMenu(folder))
            {
                iContextMenu.QueryContextMenu(
                    parentNativeMenuPtr,
                    (uint)position,
                    Interop.CMD_FIRST,
                    Interop.CMD_LAST,
                    CMF.NORMAL);

                nativeMenuPtr = Interop.GetSubMenu(parentNativeMenuPtr, position);

                if (Marshal.QueryInterface(iContextMenuPtr, ref Interop.IID_IContextMenu2,
                                           out iContextMenu2Ptr) == NativeMethods.S_OK)
                {
                    if (iContextMenu2Ptr != IntPtr.Zero)
                    {
                        try
                        {
                            iContextMenu2 =
                                (IContextMenu2)Marshal.GetTypedObjectForIUnknown(iContextMenu2Ptr, typeof(IContextMenu2));
                        }
                        catch (Exception e)
                        {
                            ShellLogger.Error($"ShellContextMenu: Error retrieving IContextMenu2 interface: {e.Message}");
                        }
                    }
                }

                if (Marshal.QueryInterface(iContextMenuPtr, ref Interop.IID_IContextMenu3,
                                           out iContextMenu3Ptr) == NativeMethods.S_OK)
                {
                    if (iContextMenu3Ptr != IntPtr.Zero)
                    {
                        try
                        {
                            iContextMenu3 =
                                (IContextMenu3)Marshal.GetTypedObjectForIUnknown(iContextMenu3Ptr, typeof(IContextMenu3));
                        }
                        catch (Exception e)
                        {
                            ShellLogger.Error($"ShellContextMenu: Error retrieving IContextMenu3 interface: {e.Message}");
                        }
                    }
                }
            }
        }
        public ShellFolderContextMenu(ShellFolder folder, FolderItemSelectAction folderItemSelected, ShellMenuCommandBuilder builder)
        {
            if (folder == null)
            {
                return;
            }

            lock (IconHelper.ComLock)
            {
                x = Cursor.Position.X;
                y = Cursor.Position.Y;

                this.folderItemSelected = folderItemSelected;

                SetupContextMenu(folder, builder);
            }
        }
예제 #3
0
        public ShellItemContextMenu(ShellItem[] files, ShellFolder parentFolder, IntPtr hwndOwner, ItemSelectAction itemSelected, bool isInteractive, bool canRename, ShellMenuCommandBuilder preBuilder, ShellMenuCommandBuilder postBuilder)
        {
            if (files == null || files.Length < 1)
            {
                return;
            }

            lock (IconHelper.ComLock)
            {
                x = Cursor.Position.X;
                y = Cursor.Position.Y;

                this.itemSelected = itemSelected;

                SetupContextMenu(files, parentFolder, hwndOwner, isInteractive, canRename, preBuilder, postBuilder);
            }
        }
        private void ConfigureMenuItems(ShellFolder folder, IntPtr contextMenu, ShellMenuCommandBuilder builder)
        {
            int numAdded = 0;

            ShellNewMenus.Clear();

            foreach (var command in builder.Commands)
            {
                if (command is ShellNewMenuCommand shellNewCommand)
                {
                    shellNewCommand.AddSubMenu(folder, numAdded, ref contextMenu);
                    ShellNewMenus.Add(shellNewCommand);
                }
                else
                {
                    Interop.AppendMenu(contextMenu, command.Flags, command.UID, command.Label);
                }

                numAdded++;
            }
        }
        private void ShowMenu(ShellFolder folder, IntPtr contextMenu)
        {
            CreateHandle(new CreateParams());

            if (EnvironmentHelper.IsWindows10DarkModeSupported)
            {
                NativeMethods.AllowDarkModeForWindow(Handle, true);
            }

            uint selected = Interop.TrackPopupMenuEx(
                contextMenu,
                TPM.RETURNCMD,
                x,
                y,
                Handle,
                IntPtr.Zero);

            if (selected >= Interop.CMD_FIRST)
            {
                if (selected <= Interop.CMD_LAST)
                {
                    // custom commands are greater than CMD_LAST, so this must be a sub menu item
                    foreach (var subMenu in ShellNewMenus)
                    {
                        if (subMenu.iContextMenu != null)
                        {
                            InvokeCommand(
                                subMenu.iContextMenu,
                                folder.IsFolder && folder.IsFileSystem ? folder.Path : null,
                                selected - Interop.CMD_FIRST,
                                new Point(x, y));
                        }
                    }
                }

                folderItemSelected?.Invoke(selected, folder.Path);
            }

            DestroyHandle();
        }
        private bool GetNewContextMenu(ShellFolder folder)
        {
            if (Interop.CoCreateInstance(
                    ref Interop.CLSID_NewMenu,
                    IntPtr.Zero,
                    CLSCTX.INPROC_SERVER,
                    ref Interop.IID_IContextMenu,
                    out iContextMenuPtr) == NativeMethods.S_OK)
            {
                iContextMenu = Marshal.GetTypedObjectForIUnknown(iContextMenuPtr, typeof(IContextMenu)) as IContextMenu;

                if (Marshal.QueryInterface(
                        iContextMenuPtr,
                        ref Interop.IID_IShellExtInit,
                        out var iShellExtInitPtr) == NativeMethods.S_OK)
                {
                    IShellExtInit iShellExtInit = Marshal.GetTypedObjectForIUnknown(
                        iShellExtInitPtr, typeof(IShellExtInit)) as IShellExtInit;

                    iShellExtInit?.Initialize(folder.AbsolutePidl, IntPtr.Zero, 0);

                    if (iShellExtInit != null)
                    {
                        Marshal.ReleaseComObject(iShellExtInit);
                    }

                    if (iShellExtInitPtr != IntPtr.Zero)
                    {
                        Marshal.Release(iShellExtInitPtr);
                    }

                    return(true);
                }
            }

            return(false);
        }
예제 #7
0
        protected bool GetIContextMenu(ShellItem[] items, ShellFolder parentFolder, IntPtr hwndOwner, out IntPtr icontextMenuPtr, out IContextMenu iContextMenu)
        {
            if (items.Length < 1)
            {
                icontextMenuPtr = IntPtr.Zero;
                iContextMenu    = null;

                return(false);
            }

            IntPtr[] pidls = new IntPtr[items.Length];

            for (int i = 0; i < items.Length; i++)
            {
                pidls[i] = items[i].RelativePidl;
            }

            if (parentFolder.ShellFolderInterface.GetUIObjectOf(
                    hwndOwner,
                    (uint)pidls.Length,
                    pidls,
                    ref Interop.IID_IContextMenu,
                    IntPtr.Zero,
                    out icontextMenuPtr) == NativeMethods.S_OK)
            {
                iContextMenu =
                    (IContextMenu)Marshal.GetTypedObjectForIUnknown(
                        icontextMenuPtr, typeof(IContextMenu));

                return(true);
            }

            icontextMenuPtr = IntPtr.Zero;
            iContextMenu    = null;

            return(false);
        }
        private void SetupContextMenu(ShellFolder folder, ShellMenuCommandBuilder builder)
        {
            try
            {
                nativeMenuPtr = Interop.CreatePopupMenu();

                ConfigureMenuItems(folder, nativeMenuPtr, builder);

                ShowMenu(folder, nativeMenuPtr);
            }
            catch (Exception e)
            {
                ShellLogger.Error($"ShellContextMenu: Error building folder context menu: {e.Message}");
            }
            finally
            {
                FreeResources();

                foreach (var subMenu in ShellNewMenus)
                {
                    subMenu.FreeResources();
                }
            }
        }
예제 #9
0
 public ShellFile(ShellFolder parentFolder, IShellFolder parentShellFolder, IntPtr relativePidl, bool isAsync = false) : base(parentFolder.AbsolutePidl, parentShellFolder, relativePidl, isAsync)
 {
     _parentItem = parentFolder;
 }
예제 #10
0
 public ShellFile(ShellFolder parentFolder, string parsingName) : base(parsingName)
 {
     _parentItem = parentFolder;
 }
예제 #11
0
        private void SetupContextMenu(ShellItem[] files, ShellFolder parentFolder, IntPtr hwndOwner, bool isInteractive, bool canRename, ShellMenuCommandBuilder preBuilder, ShellMenuCommandBuilder postBuilder)
        {
            try
            {
                if (GetIContextMenu(files, parentFolder, hwndOwner, out iContextMenuPtr, out iContextMenu))
                {
                    // get some properties about our file(s)
                    bool allFolders = ItemsAllFolders(files);

                    CMF flags = CMF.EXPLORE |
                                CMF.ITEMMENU |
                                ((Control.ModifierKeys & Keys.Shift) != 0 ? CMF.EXTENDEDVERBS : 0);

                    if (canRename)
                    {
                        flags |= CMF.CANRENAME;
                    }

                    if (!isInteractive)
                    {
                        flags |= CMF.DEFAULTONLY;
                    }

                    nativeMenuPtr = Interop.CreatePopupMenu();

                    uint numPrepended = ConfigureMenuItems(allFolders, nativeMenuPtr, preBuilder);

                    iContextMenu.QueryContextMenu(
                        nativeMenuPtr,
                        numPrepended,
                        Interop.CMD_FIRST,
                        Interop.CMD_LAST,
                        flags);

                    ConfigureMenuItems(allFolders, nativeMenuPtr, postBuilder);

                    if (isInteractive)
                    {
                        if (Marshal.QueryInterface(iContextMenuPtr, ref Interop.IID_IContextMenu2,
                                                   out iContextMenu2Ptr) == NativeMethods.S_OK)
                        {
                            if (iContextMenu2Ptr != IntPtr.Zero)
                            {
                                try
                                {
                                    iContextMenu2 =
                                        (IContextMenu2)Marshal.GetTypedObjectForIUnknown(iContextMenu2Ptr, typeof(IContextMenu2));
                                }
                                catch (Exception e)
                                {
                                    ShellLogger.Error($"ShellItemContextMenu: Error retrieving IContextMenu2 interface: {e.Message}");
                                }
                            }
                        }

                        if (Marshal.QueryInterface(iContextMenuPtr, ref Interop.IID_IContextMenu3,
                                                   out iContextMenu3Ptr) == NativeMethods.S_OK)
                        {
                            if (iContextMenu3Ptr != IntPtr.Zero)
                            {
                                try
                                {
                                    iContextMenu3 =
                                        (IContextMenu3)Marshal.GetTypedObjectForIUnknown(iContextMenu3Ptr, typeof(IContextMenu3));
                                }
                                catch (Exception e)
                                {
                                    ShellLogger.Error($"ShellItemContextMenu: Error retrieving IContextMenu3 interface: {e.Message}");
                                }
                            }
                        }

                        ShowMenu(files, allFolders);
                    }
                    else
                    {
                        uint selected = Interop.GetMenuDefaultItem(nativeMenuPtr, 0, 0);

                        HandleMenuCommand(files, selected, allFolders);
                    }
                }
                else
                {
                    ShellLogger.Error("ShellItemContextMenu: Error retrieving IContextMenu");
                }
            }
            catch (Exception e)
            {
                ShellLogger.Error($"ShellItemContextMenu: Error building context menu: {e.Message}");
            }
            finally
            {
                FreeResources();

                foreach (var subMenu in ShellNewMenus)
                {
                    subMenu.FreeResources();
                }
            }
        }
예제 #12
0
 public ShellItemContextMenu(ShellItem[] files, ShellFolder parentFolder, IntPtr hwndOwner, ItemSelectAction itemSelected, bool isInteractive, ShellMenuCommandBuilder preBuilder, ShellMenuCommandBuilder postBuilder) : this(files, parentFolder, hwndOwner, itemSelected, isInteractive, true, preBuilder, postBuilder)
 {
 }
예제 #13
0
 public ShellItemContextMenu(ShellItem[] files, ShellFolder parentFolder, IntPtr hwndOwner, ItemSelectAction itemSelected, bool isInteractive) : this(files, parentFolder, hwndOwner, itemSelected, isInteractive, new ShellMenuCommandBuilder(), new ShellMenuCommandBuilder())
 {
 }