public ShellTreeEventArgs(ShellItem shellItem) { ShellItem = shellItem; }
/// <summary> /// Gets the children. /// </summary> /// <param name="childTypes">The child types.</param> /// <returns> /// The children. /// </returns> public IEnumerable<ShellItem> GetChildren(ChildTypes childTypes) { // We'll return a list of children. var children = new List<ShellItem>(); // Create the enum flags from the childtypes. SHCONTF enumFlags = 0; if (childTypes.HasFlag(ChildTypes.Folders)) enumFlags |= SHCONTF.SHCONTF_FOLDERS; if (childTypes.HasFlag(ChildTypes.Files)) enumFlags |= SHCONTF.SHCONTF_NONFOLDERS; if (childTypes.HasFlag(ChildTypes.Hidden)) enumFlags |= SHCONTF.SHCONTF_INCLUDEHIDDEN; try { // Create an enumerator for the children. IEnumIDList pEnum; var result = ShellFolderInterface.EnumObjects(IntPtr.Zero, enumFlags, out pEnum); // Validate the result. if (result != 0) { // Throw the failure as an exception. Marshal.ThrowExceptionForHR((int)result); } // TODO: This logic should go in the pidl manager. // Enumerate the children, ten at a time. const int batchSize = 10; var pidlArray = Marshal.AllocCoTaskMem(IntPtr.Size * 10); uint itemsFetched; result = WinError.S_OK; do { result = pEnum.Next(batchSize, pidlArray, out itemsFetched); // Get each pidl. var pidls = new IntPtr[itemsFetched]; Marshal.Copy(pidlArray, pidls, 0, (int) itemsFetched); foreach (var childPidl in pidls) { // Create a new shell folder. var childShellFolder = new ShellItem(); // Initialize it. try { childShellFolder.Initialise(childPidl, this); } catch (Exception exception) { throw new InvalidOperationException("Failed to initialise child.", exception); } // Add the child. children.Add(childShellFolder); // Free the PIDL, reset the result. Marshal.FreeCoTaskMem(childPidl); } } while (result == WinError.S_OK); Marshal.FreeCoTaskMem(pidlArray); // Release the enumerator. if(Marshal.IsComObject(pEnum)) Marshal.ReleaseComObject(pEnum); } catch (Exception exception) { throw new InvalidOperationException("Failed to enumerate children.", exception); } // Sort the children. var sortedChildren = children.Where(c => c.IsFolder).ToList(); sortedChildren.AddRange(children.Where(c => !c.IsFolder)); // Return the children. return sortedChildren; }
private void OpenItemContextMenu(ShellItem itemHit, int x, int y) { // TODO: we need a min and max for the menu items. // see http://www.codeproject.com/Articles/4025/Use-Shell-ContextMenu-in-your-applications for more // The shell folder we use to get the UI object is either the folder itself if the // item is a folder, or the parent folder otherwise. var shellFolder = itemHit.IsFolder ? itemHit.ShellFolderInterface : itemHit.ParentItem.ShellFolderInterface; // The item pidl is either the folder if the item is a folder, or the combined pidl otherwise. var fullIdList = itemHit.IsFolder ? PidlManager.PidlToIdlist(itemHit.PIDL) : PidlManager.Combine(PidlManager.PidlToIdlist(itemHit.ParentItem.PIDL), PidlManager.PidlToIdlist(itemHit.RelativePIDL)); // Get the UI object of the context menu. IntPtr apidl = PidlManager.PidlsToAPidl(new IntPtr[] {PidlManager.IdListToPidl(fullIdList)}); IntPtr ppv = IntPtr.Zero; shellFolder.GetUIObjectOf(Handle, 1, apidl, Shell32.IID_IContextMenu, 0, out ppv); // If we have an item, cast it. if (ppv != IntPtr.Zero) { IContextMenu contextMenu = (IContextMenu)Marshal.GetObjectForIUnknown(ppv); var popupMenu = new ContextMenu(); contextMenu.QueryContextMenu(popupMenu.Handle, 0, 0, 65525, CMF.CMF_EXPLORE); popupMenu.Show(this, new Point(x, y)); } }
/// <summary> /// Initialises the ShellItem, from its PIDL and parent. /// </summary> /// <param name="pidl">The pidl.</param> /// <param name="parentFolder">The parent folder.</param> private void Initialise(IntPtr pidl, ShellItem parentFolder) { // Set the parent item and relative pidl. ParentItem = parentFolder; RelativePIDL = pidl; // Create the fully qualified PIDL. PIDL = Shell32.ILCombine(parentFolder.PIDL, pidl); // Use the desktop folder to get attributes. var flags = SFGAO.SFGAO_FOLDER | SFGAO.SFGAO_HASSUBFOLDER | SFGAO.SFGAO_BROWSABLE | SFGAO.SFGAO_FILESYSTEM; //todo was this parentFolder.ShellFolderInterface.GetAttributesOf(1, ref pidl, ref flags); var apidl = Marshal.AllocCoTaskMem(IntPtr.Size*1); Marshal.Copy(new IntPtr[] {pidl}, 0, apidl, 1); parentFolder.ShellFolderInterface.GetAttributesOf(1, apidl, ref flags); IsFolder = (flags & SFGAO.SFGAO_FOLDER) != 0; HasSubFolders = (flags & SFGAO.SFGAO_HASSUBFOLDER) != 0; // Get the file info. var fileInfo = new SHFILEINFO(); Shell32.SHGetFileInfo(PIDL, 0, out fileInfo, (uint)Marshal.SizeOf(fileInfo), SHGFI.SHGFI_SMALLICON | SHGFI.SHGFI_SYSICONINDEX | SHGFI.SHGFI_PIDL | SHGFI.SHGFI_DISPLAYNAME | SHGFI.SHGFI_ATTRIBUTES); // Set extended attributes. DisplayName = fileInfo.szDisplayName; Attributes = (SFGAO)fileInfo.dwAttributes; TypeName = fileInfo.szTypeName; IconIndex = fileInfo.iIcon; // Are we a folder? if (IsFolder) { // Bind the shell folder interface. IShellFolder shellFolderInterface; IntPtr ppv = IntPtr.Zero; var result = parentFolder.ShellFolderInterface.BindToObject(pidl, IntPtr.Zero, ref Shell32.IID_IShellFolder, out ppv);//out shellFolderInterface); shellFolderInterface = ((IShellFolder) Marshal.GetObjectForIUnknown(ppv)); ShellFolderInterface = shellFolderInterface; // Validate the result. if (result != 0) { // Throw the failure as an exception. Marshal.ThrowExceptionForHR((int)result); } } }
private void FireOnShellItemSelected(ShellItem shellItem) { var theEvent = OnShellItemSelected; if(theEvent != null) theEvent(this, new ShellTreeEventArgs(shellItem)); }