Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Shell扩展DLL-如果用户在文件夹空白区域内单击,如何捕获文件夹路径?_C++_Windows_Shell Extensions - Fatal编程技术网

C++ Shell扩展DLL-如果用户在文件夹空白区域内单击,如何捕获文件夹路径?

C++ Shell扩展DLL-如果用户在文件夹空白区域内单击,如何捕获文件夹路径?,c++,windows,shell-extensions,C++,Windows,Shell Extensions,使用shell扩展dll,如果用户在文件夹空白区域内单击,如何捕获文件夹路径 如果您正在实现一个shell扩展dll,那么您将获得方法中的路径作为pidlFolder参数 为了确保扩展也注册了文件夹背景,您还必须在HKCR\Directory\Background\shellex\ContextMenuHandlers下创建相应的条目。如果您正在实现外壳扩展dll,则方法中的路径将作为pidlFolder参数 为了确保您的扩展名也注册了文件夹背景,您必须在HKCR\Directory\Backg

使用shell扩展dll,如果用户在文件夹空白区域内单击,如何捕获文件夹路径

如果您正在实现一个shell扩展dll,那么您将获得方法中的路径作为pidlFolder参数


为了确保扩展也注册了文件夹背景,您还必须在HKCR\Directory\Background\shellex\ContextMenuHandlers下创建相应的条目。如果您正在实现外壳扩展dll,则方法中的路径将作为pidlFolder参数


为了确保您的扩展名也注册了文件夹背景,您必须在HKCR\Directory\Background\shellex\ContextMenuHandlers下创建相应的条目,使用VC++语言请参考Winmerge源代码

请参考这篇文章 并更新以下一些地方: 在FileContextMenuExt.cs文件中:

    #region Shell Extension Registration

    [ComRegisterFunction()]
    public static void Register(Type t)
    {
        try
        {
            ShellExtReg.RegisterShellExtContextMenuHandler(t.GUID, "Directory", 
                "CSShellExtContextMenuHandler.FileContextMenuExt Class");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message); // Log the error
            throw;  // Re-throw the exception
        }
    }

    [ComUnregisterFunction()]
    public static void Unregister(Type t)
    {
        try
        {
            ShellExtReg.UnregisterShellExtContextMenuHandler(t.GUID, "Directory");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message); // Log the error
            throw;  // Re-throw the exception
        }
    }

    #endregion
   ............... 

   public void Initialize(IntPtr pidlFolder, IntPtr pDataObj, IntPtr hKeyProgID)
    {
        if (pDataObj == IntPtr.Zero && pidlFolder == IntPtr.Zero)
        {
            throw new ArgumentException();
        }

        FORMATETC fe = new FORMATETC();
        fe.cfFormat = (short)CLIPFORMAT.CF_HDROP;
        fe.ptd = IntPtr.Zero;
        fe.dwAspect = DVASPECT.DVASPECT_CONTENT;
        fe.lindex = -1;
        fe.tymed = TYMED.TYMED_HGLOBAL;
        STGMEDIUM stm = new STGMEDIUM();          

        try
        {
            if (pDataObj != IntPtr.Zero)
            {
                // The pDataObj pointer contains the objects being acted upon. In this 
                // example, we get an HDROP handle for enumerating the selected files 
                // and folders.
                IDataObject dataObject = (IDataObject)Marshal.GetObjectForIUnknown(pDataObj);
                dataObject.GetData(ref fe, out stm);

                // Get an HDROP handle.
                IntPtr hDrop = stm.unionmember;
                if (hDrop == IntPtr.Zero)
                {
                    throw new ArgumentException();
                }

                // Determine how many files are involved in this operation.
                uint nFiles = NativeMethods.DragQueryFile(hDrop, UInt32.MaxValue, null, 0);

                // This code sample displays the custom context menu item when only 
                // one file is selected. 
                if (nFiles == 1)
                {
                    // Get the path of the file.
                    StringBuilder fileName = new StringBuilder(260);
                    if (0 == NativeMethods.DragQueryFile(hDrop, 0, fileName,
                        fileName.Capacity))
                    {
                        Marshal.ThrowExceptionForHR(WinError.E_FAIL);
                    }
                    this.selectedFile = fileName.ToString();
                }
                else
                {
                    Marshal.ThrowExceptionForHR(WinError.E_FAIL);
                }
            }

            if (pidlFolder != IntPtr.Zero) {
                StringBuilder folderName = new StringBuilder(260);
                if (0 == NativeMethods.SHGetPathFromIDList(pidlFolder, folderName))
                {
                    Marshal.ThrowExceptionForHR(WinError.E_FAIL);
                }
                this.selectedFile = folderName.ToString();
            }
        }
        finally
        {
            NativeMethods.ReleaseStgMedium(ref stm);
        }
    }
在ShellExtLib.cs文件中添加以下源:

    [DllImport("shell32.dll")]
    public static extern Int32 SHGetPathFromIDList(
        IntPtr pidl,                // Address of an item identifier list that
        // specifies a file or directory location
        // relative to the root of the namespace (the
        // desktop). 
        StringBuilder pszPath);        // Address of a buffer to receive the file system
并在ShellExtLib.cs文件中更新RegisterShellExtContextMenuHandler和UnregisterShellExtContextMenuHandler函数

    public static void RegisterShellExtContextMenuHandler(Guid clsid, 
        string fileType, string friendlyName)
    {
        if (clsid == Guid.Empty)
        {
            throw new ArgumentException("clsid must not be empty");
        }
        if (string.IsNullOrEmpty(fileType))
        {
            throw new ArgumentException("fileType must not be null or empty");
        }

        // If fileType starts with '.', try to read the default value of the 
        // HKCR\<File Type> key which contains the ProgID to which the file type 
        // is linked.
        if (fileType.StartsWith("."))
        {
            using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType))
            {
                if (key != null)
                {
                    // If the key exists and its default value is not empty, use 
                    // the ProgID as the file type.
                    string defaultVal = key.GetValue(null) as string;
                    if (!string.IsNullOrEmpty(defaultVal))
                    {
                        fileType = defaultVal;
                    }
                }
            }
        }
        else {

            // Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
            string keyName1 = string.Format(@"{0}\Background\shellex\ContextMenuHandlers\{1}",
                fileType, clsid.ToString("B"));
            using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(keyName1))
            {
                // Set the default value of the key.
                if (key != null && !string.IsNullOrEmpty(friendlyName))
                {
                    key.SetValue(null, friendlyName);
                }
            }
        }

        // Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
        string keyName = string.Format(@"{0}\shellex\ContextMenuHandlers\{1}",
            fileType, clsid.ToString("B"));
        using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(keyName))
        {
            // Set the default value of the key.
            if (key != null && !string.IsNullOrEmpty(friendlyName))
            {
                key.SetValue(null, friendlyName);
            }
        }
    }


    public static void UnregisterShellExtContextMenuHandler(Guid clsid, 
        string fileType)
    {
        if (clsid == null)
        {
            throw new ArgumentException("clsid must not be null");
        }
        if (string.IsNullOrEmpty(fileType))
        {
            throw new ArgumentException("fileType must not be null or empty");
        }

        // If fileType starts with '.', try to read the default value of the 
        // HKCR\<File Type> key which contains the ProgID to which the file type 
        // is linked.
        if (fileType.StartsWith("."))
        {
            using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType))
            {
                if (key != null)
                {
                    // If the key exists and its default value is not empty, use 
                    // the ProgID as the file type.
                    string defaultVal = key.GetValue(null) as string;
                    if (!string.IsNullOrEmpty(defaultVal))
                    {
                        fileType = defaultVal;
                    }
                }
            }
        }
        else {
            // Remove the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
            string keyName1 = string.Format(@"{0}\Background\shellex\ContextMenuHandlers\{1}",
                fileType, clsid.ToString("B"));
            Registry.ClassesRoot.DeleteSubKeyTree(keyName1, false);
        }

        // Remove the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
        string keyName = string.Format(@"{0}\shellex\ContextMenuHandlers\{1}",
            fileType, clsid.ToString("B"));
        Registry.ClassesRoot.DeleteSubKeyTree(keyName, false);
    }

使用VC++语言,请参考Winmerge源代码

请参考这篇文章 并更新以下一些地方: 在FileContextMenuExt.cs文件中:

    #region Shell Extension Registration

    [ComRegisterFunction()]
    public static void Register(Type t)
    {
        try
        {
            ShellExtReg.RegisterShellExtContextMenuHandler(t.GUID, "Directory", 
                "CSShellExtContextMenuHandler.FileContextMenuExt Class");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message); // Log the error
            throw;  // Re-throw the exception
        }
    }

    [ComUnregisterFunction()]
    public static void Unregister(Type t)
    {
        try
        {
            ShellExtReg.UnregisterShellExtContextMenuHandler(t.GUID, "Directory");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message); // Log the error
            throw;  // Re-throw the exception
        }
    }

    #endregion
   ............... 

   public void Initialize(IntPtr pidlFolder, IntPtr pDataObj, IntPtr hKeyProgID)
    {
        if (pDataObj == IntPtr.Zero && pidlFolder == IntPtr.Zero)
        {
            throw new ArgumentException();
        }

        FORMATETC fe = new FORMATETC();
        fe.cfFormat = (short)CLIPFORMAT.CF_HDROP;
        fe.ptd = IntPtr.Zero;
        fe.dwAspect = DVASPECT.DVASPECT_CONTENT;
        fe.lindex = -1;
        fe.tymed = TYMED.TYMED_HGLOBAL;
        STGMEDIUM stm = new STGMEDIUM();          

        try
        {
            if (pDataObj != IntPtr.Zero)
            {
                // The pDataObj pointer contains the objects being acted upon. In this 
                // example, we get an HDROP handle for enumerating the selected files 
                // and folders.
                IDataObject dataObject = (IDataObject)Marshal.GetObjectForIUnknown(pDataObj);
                dataObject.GetData(ref fe, out stm);

                // Get an HDROP handle.
                IntPtr hDrop = stm.unionmember;
                if (hDrop == IntPtr.Zero)
                {
                    throw new ArgumentException();
                }

                // Determine how many files are involved in this operation.
                uint nFiles = NativeMethods.DragQueryFile(hDrop, UInt32.MaxValue, null, 0);

                // This code sample displays the custom context menu item when only 
                // one file is selected. 
                if (nFiles == 1)
                {
                    // Get the path of the file.
                    StringBuilder fileName = new StringBuilder(260);
                    if (0 == NativeMethods.DragQueryFile(hDrop, 0, fileName,
                        fileName.Capacity))
                    {
                        Marshal.ThrowExceptionForHR(WinError.E_FAIL);
                    }
                    this.selectedFile = fileName.ToString();
                }
                else
                {
                    Marshal.ThrowExceptionForHR(WinError.E_FAIL);
                }
            }

            if (pidlFolder != IntPtr.Zero) {
                StringBuilder folderName = new StringBuilder(260);
                if (0 == NativeMethods.SHGetPathFromIDList(pidlFolder, folderName))
                {
                    Marshal.ThrowExceptionForHR(WinError.E_FAIL);
                }
                this.selectedFile = folderName.ToString();
            }
        }
        finally
        {
            NativeMethods.ReleaseStgMedium(ref stm);
        }
    }
在ShellExtLib.cs文件中添加以下源:

    [DllImport("shell32.dll")]
    public static extern Int32 SHGetPathFromIDList(
        IntPtr pidl,                // Address of an item identifier list that
        // specifies a file or directory location
        // relative to the root of the namespace (the
        // desktop). 
        StringBuilder pszPath);        // Address of a buffer to receive the file system
并在ShellExtLib.cs文件中更新RegisterShellExtContextMenuHandler和UnregisterShellExtContextMenuHandler函数

    public static void RegisterShellExtContextMenuHandler(Guid clsid, 
        string fileType, string friendlyName)
    {
        if (clsid == Guid.Empty)
        {
            throw new ArgumentException("clsid must not be empty");
        }
        if (string.IsNullOrEmpty(fileType))
        {
            throw new ArgumentException("fileType must not be null or empty");
        }

        // If fileType starts with '.', try to read the default value of the 
        // HKCR\<File Type> key which contains the ProgID to which the file type 
        // is linked.
        if (fileType.StartsWith("."))
        {
            using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType))
            {
                if (key != null)
                {
                    // If the key exists and its default value is not empty, use 
                    // the ProgID as the file type.
                    string defaultVal = key.GetValue(null) as string;
                    if (!string.IsNullOrEmpty(defaultVal))
                    {
                        fileType = defaultVal;
                    }
                }
            }
        }
        else {

            // Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
            string keyName1 = string.Format(@"{0}\Background\shellex\ContextMenuHandlers\{1}",
                fileType, clsid.ToString("B"));
            using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(keyName1))
            {
                // Set the default value of the key.
                if (key != null && !string.IsNullOrEmpty(friendlyName))
                {
                    key.SetValue(null, friendlyName);
                }
            }
        }

        // Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
        string keyName = string.Format(@"{0}\shellex\ContextMenuHandlers\{1}",
            fileType, clsid.ToString("B"));
        using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(keyName))
        {
            // Set the default value of the key.
            if (key != null && !string.IsNullOrEmpty(friendlyName))
            {
                key.SetValue(null, friendlyName);
            }
        }
    }


    public static void UnregisterShellExtContextMenuHandler(Guid clsid, 
        string fileType)
    {
        if (clsid == null)
        {
            throw new ArgumentException("clsid must not be null");
        }
        if (string.IsNullOrEmpty(fileType))
        {
            throw new ArgumentException("fileType must not be null or empty");
        }

        // If fileType starts with '.', try to read the default value of the 
        // HKCR\<File Type> key which contains the ProgID to which the file type 
        // is linked.
        if (fileType.StartsWith("."))
        {
            using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType))
            {
                if (key != null)
                {
                    // If the key exists and its default value is not empty, use 
                    // the ProgID as the file type.
                    string defaultVal = key.GetValue(null) as string;
                    if (!string.IsNullOrEmpty(defaultVal))
                    {
                        fileType = defaultVal;
                    }
                }
            }
        }
        else {
            // Remove the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
            string keyName1 = string.Format(@"{0}\Background\shellex\ContextMenuHandlers\{1}",
                fileType, clsid.ToString("B"));
            Registry.ClassesRoot.DeleteSubKeyTree(keyName1, false);
        }

        // Remove the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
        string keyName = string.Format(@"{0}\shellex\ContextMenuHandlers\{1}",
            fileType, clsid.ToString("B"));
        Registry.ClassesRoot.DeleteSubKeyTree(keyName, false);
    }

你试着打电话了吗?@dario_ramos:错误的功能。在某些系统上,所有资源管理器窗口都有一个资源管理器进程。如果在两个不同的文件夹上打开了两个窗口,则GetCurrentDir不能同时返回这两个窗口。若您在单独的过程中启用了“打开新窗口”,那个么它就可以工作了。不一定。你试过打电话了吗?@dario_ramos:错误的函数。在某些系统上,所有资源管理器窗口都有一个资源管理器进程。如果在两个不同的文件夹上打开了两个窗口,则GetCurrentDir不能同时返回这两个窗口。若您在单独的过程中启用了“打开新窗口”,那个么它就可以工作了。但不保证。如果我们在文件夹ie中单击,则pidlFolder将不在我的shell扩展中。右键单击文件夹背景空白区域时,pidlFolder不为NULL。但是有一个问题,如果我使用pidlFolder获取路径,QueryContextMenu函数未初始化。您必须注册后台扩展名。值得一提的是,您可以使用SHGetPathFromIDList将此pidlFolder转换为路径字符串。如果我们在文件夹ie内单击,则空区域中的pidlFolder将为Null而不是在我的shell扩展名中。右键单击文件夹背景空白区域时,pidlFolder不为NULL。但存在一个问题,如果使用pidlFolder获取路径,QueryContextMenu函数将不处于hiiting状态。您必须注册后台扩展名。值得一提的是,您可以使用SHGetPathFromIDList将此pidlFolder转换为路径字符串。