⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shellitem.cs

📁 C#界面编程
💻 CS
📖 第 1 页 / 共 4 页
字号:
using System;
using System.Windows.Forms;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

namespace ShellDll
{
    public sealed class ShellItem : IEnumerable, IDisposable, IComparable
    {
        #region Fields

        private ShellBrowser browser;

        private ShellItem parentItem;
        private IShellFolder shellFolder;
        private IntPtr shellFolderPtr;
        private ShellItemCollection subFiles, subFolders;

        private PIDL pidlRel;

        private short sortFlag;
        private int imageIndex, selectedImageIndex;

        private bool isFolder, isLink, isShared, isFileSystem,
                     isHidden, hasSubfolder, isBrowsable, isDisk, filesExpanded,
                     foldersExpanded, canRename, updateShellFolder, canRead;
        
        private string text, path, type;

        private bool disposed = false;

        #endregion

        #region Constructors

        internal ShellItem(ShellBrowser browser, IntPtr pidl, IntPtr shellFolderPtr)
        {
            this.browser = browser;

            this.shellFolderPtr = shellFolderPtr;
            this.shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(shellFolderPtr, typeof(IShellFolder));
            subFiles = new ShellItemCollection(this);
            subFolders = new ShellItemCollection(this);

            pidlRel = new PIDL(pidl, false);

            text = "Desktop";
            path = "Desktop";

            SetAttributesDesktop(this);

            ShellAPI.SHFILEINFO info = new ShellAPI.SHFILEINFO();
            ShellAPI.SHGetFileInfo(pidlRel.Ptr, 0, ref info, ShellAPI.cbFileInfo,
                ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.TYPENAME | ShellAPI.SHGFI.SYSICONINDEX);

            type = info.szTypeName;

            ShellImageList.SetIconIndex(this, info.iIcon, false);
            ShellImageList.SetIconIndex(this, info.iIcon, true);

            sortFlag = 1;
        }

        internal ShellItem(ShellBrowser browser, ShellItem parentItem, IntPtr pidl, IntPtr shellFolderPtr)
        {
            this.browser = browser;

            this.parentItem = parentItem;
            this.shellFolderPtr = shellFolderPtr;
            this.shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(shellFolderPtr, typeof(IShellFolder));
            subFiles = new ShellItemCollection(this);
            subFolders = new ShellItemCollection(this);

            pidlRel = new PIDL(pidl, false);

            SetText(this);
            SetPath(this);
            SetAttributesFolder(this);
            SetInfo(this);                       

            sortFlag = MakeSortFlag(this);
        }

        internal ShellItem(ShellBrowser browser, ShellItem parentItem, IntPtr pidl)
        {
            this.browser = browser;

            this.parentItem = parentItem;

            pidlRel = new PIDL(pidl, false);

            SetText(this);
            SetPath(this);
            SetAttributesFile(this);
            SetInfo(this);                        

            sortFlag = MakeSortFlag(this);
        }

        ~ShellItem()
        {
            ((IDisposable)this).Dispose();
        }

        #endregion

        #region Init Methods

        private static void SetText(ShellItem item)
        {
            IntPtr strr = Marshal.AllocCoTaskMem(ShellAPI.MAX_PATH * 2 + 4);
            Marshal.WriteInt32(strr, 0, 0);
            StringBuilder buf = new StringBuilder(ShellAPI.MAX_PATH);

            if (item.ParentItem.ShellFolder.GetDisplayNameOf(
                            item.PIDLRel.Ptr,
                            ShellAPI.SHGNO.INFOLDER,
                            strr) == ShellAPI.S_OK)
            {
                ShellAPI.StrRetToBuf(strr, item.PIDLRel.Ptr, buf, ShellAPI.MAX_PATH);
                item.text = buf.ToString();
            }

            Marshal.FreeCoTaskMem(strr);
        }

        private static void SetPath(ShellItem item)
        {
            IntPtr strr = Marshal.AllocCoTaskMem(ShellAPI.MAX_PATH * 2 + 4);
            Marshal.WriteInt32(strr, 0, 0);
            StringBuilder buf = new StringBuilder(ShellAPI.MAX_PATH);

            if (item.ParentItem.ShellFolder.GetDisplayNameOf(
                            item.PIDLRel.Ptr,
                            ShellAPI.SHGNO.FORADDRESSBAR | ShellAPI.SHGNO.FORPARSING,
                            strr) == ShellAPI.S_OK)
            {
                ShellAPI.StrRetToBuf(strr, item.PIDLRel.Ptr, buf, ShellAPI.MAX_PATH);
                item.path = buf.ToString();
            }

            Marshal.FreeCoTaskMem(strr);
        }

        private static void SetInfo(ShellItem item)
        {
            PIDL pidlFull = item.PIDLFull;

            ShellAPI.SHFILEINFO info = new ShellAPI.SHFILEINFO();
            ShellAPI.SHGetFileInfo(pidlFull.Ptr, 0, ref info, ShellAPI.cbFileInfo,
                ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.TYPENAME | ShellAPI.SHGFI.SYSICONINDEX);

            pidlFull.Free();

            ShellImageList.SetIconIndex(item, info.iIcon, false);
            ShellImageList.SetIconIndex(item, info.iIcon, true);

            item.type = info.szTypeName;
        }

        private static void SetAttributesDesktop(ShellItem item)
        {
            item.isFolder = true;
            item.isLink = false;
            item.isShared = false;
            item.isFileSystem = true;
            item.isHidden = false;
            item.hasSubfolder = true;
            item.isBrowsable = true;
            item.canRename = false;
            item.canRead = true;
        }

        private static void SetAttributesFolder(ShellItem item)
        {
            // file/folder attributes
            ShellAPI.SFGAO attribs = 
                ShellAPI.SFGAO.SHARE |
                ShellAPI.SFGAO.FILESYSTEM |
                ShellAPI.SFGAO.HIDDEN |
                ShellAPI.SFGAO.HASSUBFOLDER |
                ShellAPI.SFGAO.BROWSABLE |
                ShellAPI.SFGAO.CANRENAME | 
                ShellAPI.SFGAO.STORAGE;
            item.ParentItem.ShellFolder.GetAttributesOf(
                1, new IntPtr[] { item.PIDLRel.Ptr }, ref attribs);
            
            item.isFolder = true;
            item.isLink = false;
            item.isShared = (attribs & ShellAPI.SFGAO.SHARE) != 0;
            item.isFileSystem = (attribs & ShellAPI.SFGAO.FILESYSTEM) != 0;
            item.isHidden = (attribs & ShellAPI.SFGAO.HIDDEN) != 0;
            item.hasSubfolder = (attribs & ShellAPI.SFGAO.HASSUBFOLDER) != 0;
            item.isBrowsable = (attribs & ShellAPI.SFGAO.BROWSABLE) != 0;
            item.canRename = (attribs & ShellAPI.SFGAO.CANRENAME) != 0;
            item.canRead = (attribs & ShellAPI.SFGAO.STORAGE) != 0;

            item.isDisk = (item.path.Length == 3 && item.path.EndsWith(":\\"));
        }

        private static void SetAttributesFile(ShellItem item)
        {
            // file/folder attributes
            ShellAPI.SFGAO attribs =
                ShellAPI.SFGAO.LINK |
                ShellAPI.SFGAO.SHARE | 
                ShellAPI.SFGAO.FILESYSTEM |
                ShellAPI.SFGAO.HIDDEN |
                ShellAPI.SFGAO.CANRENAME |
                ShellAPI.SFGAO.STREAM;
            item.ParentItem.ShellFolder.GetAttributesOf(
                1, new IntPtr[] { item.PIDLRel.Ptr }, ref attribs);

            item.isFolder = false;
            item.isLink = (attribs & ShellAPI.SFGAO.LINK) != 0;
            item.isShared = (attribs & ShellAPI.SFGAO.SHARE) != 0;
            item.isFileSystem = (attribs & ShellAPI.SFGAO.FILESYSTEM) != 0;
            item.isHidden = (attribs & ShellAPI.SFGAO.HIDDEN) != 0;
            item.hasSubfolder = false;
            item.isBrowsable = false;
            item.canRename = (attribs & ShellAPI.SFGAO.CANRENAME) != 0;
            item.canRead = (attribs & ShellAPI.SFGAO.STREAM) != 0;

            item.isDisk = false;
        }        

        #endregion

        #region Browse Methods

        internal bool Expand(bool expandFiles, bool expandFolders, IntPtr winHandle)
        {
            if (((expandFiles && !filesExpanded) || !expandFiles) &&
                ((expandFolders && !foldersExpanded) || !expandFolders) &&
                (expandFiles || expandFolders) && ShellFolder != null && !disposed)
            {
                #region Fields

                IntPtr fileEnumPtr = IntPtr.Zero, folderEnumPtr = IntPtr.Zero;
                IEnumIDList fileEnum = null, folderEnum = null;
                IntPtr pidlSubItem;
                int celtFetched;

                ShellAPI.SHCONTF fileFlag =
                        ShellAPI.SHCONTF.NONFOLDERS |
                        ShellAPI.SHCONTF.INCLUDEHIDDEN;

                ShellAPI.SHCONTF folderFlag =
                        ShellAPI.SHCONTF.FOLDERS |
                        ShellAPI.SHCONTF.INCLUDEHIDDEN;

                #endregion

                try
                {
                    #region Add Files

                    if (expandFiles)
                    {
                        if (this.Equals(browser.DesktopItem) || parentItem.Equals(browser.DesktopItem))
                        {
                            if (ShellFolder.EnumObjects(
                                    winHandle,
                                    fileFlag,
                                    out fileEnumPtr) == ShellAPI.S_OK)
                            {
                                fileEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(fileEnumPtr, typeof(IEnumIDList));
                                ShellAPI.SFGAO attribs = ShellAPI.SFGAO.FOLDER;
                                while (fileEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1)
                                {
                                    ShellFolder.GetAttributesOf(1, new IntPtr[] { pidlSubItem }, ref attribs);

                                    if ((attribs & ShellAPI.SFGAO.FOLDER) == 0)
                                    {
                                        ShellItem newItem = new ShellItem(browser, this, pidlSubItem);

                                        if (!subFolders.Contains(newItem.Text))
                                            subFiles.Add(newItem);
                                    }
                                    else
                                        Marshal.FreeCoTaskMem(pidlSubItem);
                                }

                                subFiles.Sort();
                                filesExpanded = true;
                            }
                        }
                        else
                        {
                            if (ShellFolder.EnumObjects(
                                    winHandle,
                                    fileFlag,
                                    out fileEnumPtr) == ShellAPI.S_OK)
                            {
                                fileEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(fileEnumPtr, typeof(IEnumIDList));
                                while (fileEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1)
                                {
                                    ShellItem newItem = new ShellItem(browser, this, pidlSubItem);
                                    subFiles.Add(newItem);
                                }

                                subFiles.Sort();
                                filesExpanded = true;
                            }
                        }
                    }

                    #endregion

                    #region Add Folders

                    if (expandFolders)
                    {
                        if (ShellFolder.EnumObjects(
                                    winHandle,
                                    folderFlag,
                                    out folderEnumPtr) == ShellAPI.S_OK)
                        {
                            folderEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(folderEnumPtr, typeof(IEnumIDList));
                            while (folderEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1)
                            {
                                IntPtr shellFolderPtr;
                                if (ShellFolder.BindToObject(
                                            pidlSubItem,
                                            IntPtr.Zero,
                                            ref ShellAPI.IID_IShellFolder,
                                            out shellFolderPtr) == ShellAPI.S_OK)
                                {
                                    ShellItem newItem = new ShellItem(
                                        browser,
                                        this,
                                        pidlSubItem,
                                        shellFolderPtr);
                                    subFolders.Add(newItem);
                                }
                            }

                            subFolders.Sort();
                            foldersExpanded = true;
                        }
                    }

                    #endregion
                }
                catch (Exception) { }
                finally
                {
                    #region Free

                    if (folderEnum != null)
                    {
                        Marshal.ReleaseComObject(folderEnum);
                        Marshal.Release(folderEnumPtr);
                    }

                    if (fileEnum != null)
                    {
                        Marshal.ReleaseComObject(fileEnum);
                        Marshal.Release(fileEnumPtr);
                    }

                    #endregion
                }
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -