Ejemplo n.º 1
0
        public NativeDirectoryInfo(WinAPI.CSIDL type = WinAPI.CSIDL.CSIDL_DRIVES)
        {
            // new ShellItem() can only be called once.
            if (haveRootShell)
            {
                throw new Exception("The Desktop shell item already exists so cannot be created again.");
            }

            // Obtain the root IShellFolder interface.
            int hRes = WinAPI.SHGetDesktopFolder(ref _desktopShellFolder);

            if (hRes != 0)
            {
                Marshal.ThrowExceptionForHR(hRes);
            }

            // Now get the PIDL for the Desktop shell item.
            hRes = WinAPI.SHGetSpecialFolderLocation(IntPtr.Zero, type, ref _pIDL);

            if (hRes != 0)
            {
                Marshal.ThrowExceptionForHR(hRes);
            }

            if (type != WinAPI.CSIDL.CSIDL_DESKTOP)
            {
                hRes = (int)_desktopShellFolder.BindToObject(_pIDL, IntPtr.Zero, ref WinAPI.IID_IShellFolder,
                                                             out _shellFolder);
                _rootShellFolder = ShellFolder;
            }
            else
            {
                _rootShellFolder = DesktopShellFolder;
                _shellFolder     = DesktopShellFolder;
            }

            if (hRes != 0)
            {
                Marshal.ThrowExceptionForHR(hRes);
            }

            // Now retrieve some attributes for the root shell item.
            shInfo = new WinAPI.SHFILEINFO();
            WinAPI.SHGetFileInfo(_pIDL, 0, out shInfo, (uint)Marshal.SizeOf(shInfo), vFlags);

            // Set the arributes to object properties.
            DisplayName   = shInfo.szDisplayName;
            IconIndex     = shInfo.iIcon;
            IsFolder      = true;
            haveRootShell = true;
        }
Ejemplo n.º 2
0
        private static void ShowShellContextMenu(IEnumerable <string> paths, IntPtr windowHandle, IntVector2 mousePos)
        {
            WinAPI.IShellFolder desktop = null;
            var pathPIDL = IntPtr.Zero;

            WinAPI.IShellFolder shellFolder = null;
            uint pchEaten = 0;

            WinAPI.SFGAO attr = 0;
            IntPtr       ppv;
            var          filePIDL = IntPtr.Zero;

            WinAPI.IContextMenu iCMenu = null;
            var shellContextMenu       = IntPtr.Zero;
            var callbackWnd            = IntPtr.Zero;

            WinAPI.IContextMenu2 iCMenu2 = null;
            Action Finalize = () => {
                if (iCMenu2 != null)
                {
                    Marshal.FinalReleaseComObject(iCMenu2);
                }
                if (iCMenu != null)
                {
                    Marshal.FinalReleaseComObject(iCMenu);
                }
                if (shellFolder != null)
                {
                    Marshal.FinalReleaseComObject(shellFolder);
                }
                if (desktop != null)
                {
                    Marshal.FinalReleaseComObject(desktop);
                }
                if (filePIDL != IntPtr.Zero)
                {
                    WinAPI.CoTaskMemFree(filePIDL);
                }
                if (pathPIDL != IntPtr.Zero)
                {
                    WinAPI.CoTaskMemFree(pathPIDL);
                }
                if (shellContextMenu != IntPtr.Zero)
                {
                    WinAPI.DestroyMenu(shellContextMenu);
                }
                if (callbackWnd != IntPtr.Zero)
                {
                    WinAPI.DestroyWindow(callbackWnd);
                }
            };
            Action <int> checkHResult = (result) => {
                if (result != 0)
                {
                    Finalize();
                    Marshal.ThrowExceptionForHR(result);
                }
            };
            int r     = 0;
            var pidls = new List <IntPtr>();

            foreach (var path in paths)
            {
                string dir      = Path.GetDirectoryName(path) ?? "";
                string filename = Path.GetFileNameWithoutExtension(path);
                string fileExt  = Path.GetExtension(path);
                string pathRoot = Path.GetPathRoot(path);
                if (!dir.StartsWith(pathRoot))
                {
                    dir = Path.Combine(pathRoot, dir);
                }
                if (!string.IsNullOrEmpty(filename) && !string.IsNullOrEmpty(fileExt))
                {
                    filename += fileExt;
                }
                r = WinAPI.SHGetDesktopFolder(out desktop);
                checkHResult(r);
                if (string.IsNullOrEmpty(filename))
                {
                    r = WinAPI.SHGetSpecialFolderLocation(IntPtr.Zero, WinAPI.CSIDL.CSIDL_DRIVES, ref pathPIDL);
                    checkHResult(r);
                    r = desktop.BindToObject(pathPIDL, IntPtr.Zero, ref WinAPI.Guid_IShellFolder.IID_IShellFolder, out ppv);
                    checkHResult(r);
                    shellFolder = (WinAPI.IShellFolder)Marshal.GetObjectForIUnknown(ppv);
                    r           = shellFolder.ParseDisplayName(windowHandle, IntPtr.Zero, dir, ref pchEaten, out filePIDL, ref attr);
                    checkHResult(r);
                }
                else
                {
                    r = desktop.ParseDisplayName(windowHandle, IntPtr.Zero, dir, ref pchEaten, out pathPIDL, ref attr);
                    checkHResult(r);
                    r = desktop.BindToObject(pathPIDL, IntPtr.Zero, ref WinAPI.IID_IShellFolder, out ppv);
                    checkHResult(r);
                    shellFolder = (WinAPI.IShellFolder)Marshal.GetObjectForIUnknown(ppv);
                    r           = shellFolder.ParseDisplayName(windowHandle, IntPtr.Zero, filename, ref pchEaten, out filePIDL, ref attr);
                    checkHResult(r);
                }
                pidls.Add(filePIDL);
            }
            r = shellFolder.GetUIObjectOf(windowHandle, (uint)pidls.Count, ref pidls.ToArray()[0], ref WinAPI.IID_IContextMenu, 0, out ppv);
            checkHResult(r);
            iCMenu           = (WinAPI.IContextMenu)Marshal.GetObjectForIUnknown(ppv);
            shellContextMenu = WinAPI.CreatePopupMenu();
            r = iCMenu.QueryContextMenu(shellContextMenu, 0, 1, 0x7FFF, WinAPI.CMF.CMF_EXPLORE);
            if ((r & 0x80000000) == 0)
            {
                var ppv2 = IntPtr.Zero;
                Marshal.QueryInterface(ppv, ref WinAPI.IID_IContextMenu2, out ppv2);
                iCMenu2     = (WinAPI.IContextMenu2)Marshal.GetObjectForIUnknown(ppv2);
                callbackWnd = CreateMenuCallbackWnd(iCMenu2);
                var popupMenuResult = WinAPI.TrackPopupMenuEx(shellContextMenu,
                                                              WinAPI.TPM_LEFTALIGN | WinAPI.TPM_LEFTBUTTON | WinAPI.TPM_RIGHTBUTTON | WinAPI.TPM_RETURNCMD,
                                                              mousePos.X, mousePos.Y, callbackWnd, IntPtr.Zero);
                if (popupMenuResult > 0)
                {
                    var iCmd = popupMenuResult - 1;
                    var CMD  = new WinAPI.CMINVOKECOMMANDINFO {
                        cbSize = (uint)Marshal.SizeOf(typeof(WinAPI.CMINVOKECOMMANDINFO)),
                        hwnd   = windowHandle,
                        verb   = (IntPtr)iCmd,
                        nShow  = 1,                        // SW_SHOWNORMAL
                    };
                    r = iCMenu.InvokeCommand(ref CMD);
                    checkHResult(r);
                }
            }
            Finalize();
        }