c ++ - Shell Extension DLL - hvordan man registrerer mappestien, hvis bruger klikker inde i mappen tomt område?

Indlæg af Hanne Mølgaard Plasc

Problem



Ved hjælp af shell extension dll, hvordan fanger du mappestien, hvis bruger klikker inde i mappen tomt område?

Bedste reference


Hvis du implementerer en shell extension dll, så får du stien i din IShellExtInit :: Initialize () metode som parameteren pidlFolder. [6]


For at sikre, at din udvidelse også er registreret til baggrundsmapper, skal du også oprette de relevante poster under HKCRDirectoryBackgroundshellexContextMenuHandlers

Andre referencer 1


Med VC ++ sprog henvises til Winmerge souce kode
http://sourceforge.net/p/winmerge/code/HEAD/tree/trunk/ShellExtension/[7]


Med C # bedes du henvise til denne artikel
http://www.codeproject.com/Articles/174369/How-to-Write-Windows-Shell-Extension-with-NET-Lang
og opdater noget sted bellow:
På FileContextMenuExt.cs fil: [8]


...............


    #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);
        }
    }


På ShellExtLib.cs fil Tilføj følgende kilde:


    [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


Og opdater RegisterShellExtContextMenuHandler og UnregisterShellExtContextMenuHandler funktionen på ShellExtLib.cs fil


    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>shellexContextMenuHandlers{<CLSID>}.
            string keyName1 = string.Format(@"{0}BackgroundshellexContextMenuHandlers{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>shellexContextMenuHandlers{<CLSID>}.
        string keyName = string.Format(@"{0}shellexContextMenuHandlers{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>shellexContextMenuHandlers{<CLSID>}.
            string keyName1 = string.Format(@"{0}BackgroundshellexContextMenuHandlers{1}",
                fileType, clsid.ToString("B"));
            Registry.ClassesRoot.DeleteSubKeyTree(keyName1, false);
        }

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