Пример #1
0
        /// <summary>
        /// Retrieves an OLE interface that can be used to carry out actions on the
        /// specified file objects or folders. Return value: error code, if any
        /// </summary>
        /// <param name="hwndOwner">Handle to the owner window that the client should specify if it displays a dialog box or message box.</param>
        /// <param name="cidl">Number of file objects or subfolders specified in the apidl parameter.</param>
        /// <param name="apidl">Address of an array of pointers to ITEMIDLIST  structures, each of which  uniquely identifies a file object or subfolder relative to the parent folder.</param>
        /// <param name="riid">Identifier of the COM interface object to return.</param>
        /// <param name="rgfReserved">Reserved.</param>
        /// <param name="ppv">Pointer to the requested interface.</param>
        /// <returns>
        /// If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
        /// </returns>
        int IShellFolder.GetUIObjectOf(IntPtr hwndOwner, uint cidl, IntPtr apidl, ref Guid riid, uint rgfReserved, out IntPtr ppv)
        {
            //  Get the ID lists from the array of PIDLs provided.
            var idLists = PidlManager.APidlToIdListArray(apidl, (int)cidl);

            if (riid == typeof(IContextMenu).GUID || riid == typeof(IContextMenu2).GUID || riid == typeof(IContextMenu3).GUID)
            {
                //  If the folder implments the context menu provider, we can use that.
                var contextMenuProvider = proxyFolder as IShellNamespaceFolderContextMenuProvider;
                if (contextMenuProvider != null)
                {
                    ppv = Marshal.GetComInterfaceForObject(contextMenuProvider.CreateContextMenu(idListAbsolute, idLists),
                                                           typeof(IContextMenu));
                    return(WinError.S_OK);
                }
                var dcm = new DEFCONTEXTMENU
                {
                    hwnd                = hwndOwner,
                    pcmcb               = null,
                    pidlFolder          = PidlManager.IdListToPidl(idListAbsolute),
                    psf                 = this,
                    cidl                = cidl,
                    apidl               = apidl,
                    punkAssociationInfo = IntPtr.Zero,
                    cKeys               = 0,
                    aKeys               = null
                };

                //  Create the default context menu.
                var result = Shell32.SHCreateDefaultContextMenu(dcm, riid, out ppv);
            }
            else if (riid == Shell32.IID_ExtractIconW)
            {
                //  If we've been asked for an icon, it should only be for a single PIDL.
                if (idLists.Length != 1)
                {
                    Diagnostics.Logging.Error(string.Format("The Shell Folder Impl for folder {0} has been asked for icons for multiple files at once, this is not supportedd.",
                                                            proxyFolder.GetDisplayName(DisplayNameContext.Normal)));
                    ppv = IntPtr.Zero;
                    return(WinError.E_FAIL);
                }

                //  Get the idlist and item.
                var idList = idLists[0];
                var item   = GetChildItem(idList);

                //  Now get the icon. If we don't provide one we'll use the defaults.
                var icon = item.GetIcon();
                if (icon == null)
                {
                    ProvideDefaultIExtractIcon(item is IShellNamespaceFolder, out ppv);
                    return(WinError.S_OK);
                }
                else
                {
                    //  Create an icon provider.
                    var provider = new Components.ExtractIconImpl()
                    {
                        DoNotCacheIcons = false, Icon = icon
                    };
                    ppv = Marshal.GetComInterfaceForObject(provider, typeof(IExtractIconW));
                    return(WinError.S_OK);
                }
            }
            else if (riid == Shell32.IID_IDataObject)
            {
                //  Create the data object.
                Shell32.SHCreateDataObject(PidlManager.IdListToPidl(idListAbsolute), cidl, apidl, null, riid, out ppv);
            }
            else if (riid == Shell32.IID_IQueryAssociations)
            {
                //  If we've been asked for a query associations, it should only be for a single PIDL.
                if (idLists.Length != 1)
                {
                    Diagnostics.Logging.Error(string.Format("The Shell Folder Impl for folder {0} has been asked for query associations for multiple files at once, this is not supportedd.",
                                                            proxyFolder.GetDisplayName(DisplayNameContext.Normal)));
                    ppv = IntPtr.Zero;
                    return(WinError.E_FAIL);
                }
                var item     = GetChildItem(idLists[0]);
                var isFolder = item is IShellNamespaceFolder;

                if (isFolder)
                {
                    //  todo perhaps a good class name would simply be the
                    //  name of the item type? or an attribute that uses the classname as a
                    //  fallback.
                    var associations = new ASSOCIATIONELEMENT[]
                    {
                        new ASSOCIATIONELEMENT
                        {
                            ac       = ASSOCCLASS.ASSOCCLASS_PROGID_STR,
                            hkClass  = IntPtr.Zero,
                            pszClass = "FolderViewSampleType"
                        },
                        new ASSOCIATIONELEMENT
                        {
                            ac       = ASSOCCLASS.ASSOCCLASS_FOLDER,
                            hkClass  = IntPtr.Zero,
                            pszClass = "FolderViewSampleType"
                        }
                    };
                    Shell32.AssocCreateForClasses(associations, (uint)associations.Length, riid, out ppv);
                }
                else
                {
                    var associations = new ASSOCIATIONELEMENT[]
                    {
                        new ASSOCIATIONELEMENT
                        {
                            ac       = ASSOCCLASS.ASSOCCLASS_PROGID_STR,
                            hkClass  = IntPtr.Zero,
                            pszClass = "FolderViewSampleType"
                        }
                    };
                    Shell32.AssocCreateForClasses(associations, (uint)associations.Length, riid, out ppv);
                }
            }

            /*   } */


            //  We have a set of child pidls (i.e. length one). We can now offer interfaces such as:

            /*
             * IContextMenu	The cidl parameter can be greater than or equal to one.
             * IContextMenu2	The cidl parameter can be greater than or equal to one.
             * IDataObject	The cidl parameter can be greater than or equal to one.
             * IDropTarget	The cidl parameter can only be one.
             * IExtractIcon	The cidl parameter can only be one.
             * IQueryInfo	The cidl parameter can only be one.
             * */

            //  IID_IExtractIconW
            //  IID_IDataObject
            //  IID_IQueryAssociations
            //  Currently, we don't offer any extra child item UI objects.
            ppv = IntPtr.Zero;
            return(WinError.E_NOINTERFACE);
        }