Esempio n. 1
0
 public static extern int AssocCreateForClasses(ASSOCIATIONELEMENT[] rgClasses, uint cClasses, Guid riid, out IntPtr ppv);
Esempio n. 2
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() { DontCacheIcons = 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;
        }