📄 shellitem.cs
字号:
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 + -