像@astef一样,我也需要在WPF中使用它,但是我确实需要文件夹的图标。
由于驱动器和文件夹没有扩展名,因此我使用DirectoryInfo来确定哪一个是哪一个。
对于文件夹,我始终使用其关闭的图标,但是您可以轻松地将其扩展到考虑打开或关闭。
public static class IconManager
{
private static readonly Dictionary<string, ImageSource> _smallIconCache = new Dictionary<string, ImageSource>();
private static readonly Dictionary<string, ImageSource> _largeIconCache = new Dictionary<string, ImageSource>();
public static ImageSource FindIconForFilename(string fileName, bool large)
{
DirectoryInfo di = new DirectoryInfo(fileName);
string extension = di.Extension;
if (extension == null)
return null;
if (extension == string.Empty && di.Root.FullName == di.FullName) {
extension = "ROOT";
}
if (extension == string.Empty && di.Attributes.HasFlag(FileAttributes.Directory)) {
extension = "FOLDER";
} else {
if (di.Attributes.HasFlag(FileAttributes.Directory) && extension != "ROOT") {
extension = "FOLDER";
}
}
var cache = large ? _largeIconCache : _smallIconCache;
ImageSource icon;
if (cache.TryGetValue(extension, out icon))
return icon;
if (di.Attributes.HasFlag(FileAttributes.Directory) && extension != "ROOT") {
icon = IconReader.GetFolderIcon(fileName, large ? IconReader.IconSize.Large : IconReader.IconSize.Small, IconReader.FolderType.Closed).ToImageSource();
} else {
icon = IconReader.GetFileIcon(fileName, large ? IconReader.IconSize.Large : IconReader.IconSize.Small, false).ToImageSource();
}
if (extension != "ROOT") cache.Add(extension, icon);
return icon;
}
static ImageSource ToImageSource(this System.Drawing.Icon icon)
{
var imageSource = Imaging.CreateBitmapSourceFromHIcon(
icon.Handle,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
return imageSource;
}
static class IconReader
{
public enum IconSize
{
Large = 0,
Small = 1
}
public static System.Drawing.Icon GetFileIcon(string name, IconSize size, bool linkOverlay)
{
var shfi = new Shell32.SHFILEINFO();
var flags = Shell32.SHGFI_ICON;
if (linkOverlay) flags += Shell32.SHGFI_LINKOVERLAY;
if (IconSize.Small == size)
flags += Shell32.SHGFI_SMALLICON;
else
flags += Shell32.SHGFI_SMALLICON;
Shell32.SHGetFileInfo(name,
Shell32.FILE_ATTRIBUTE_NORMAL,
ref shfi,
(uint)Marshal.SizeOf(shfi),
flags);
var icon = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shfi.hIcon).Clone();
User32.DestroyIcon(shfi.hIcon);
return icon;
}
public enum FolderType
{
Open = 0,
Closed = 1
}
public static System.Drawing.Icon GetFolderIcon(string name, IconSize size, FolderType folderType)
{
uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_SYSICONINDEX;
if (FolderType.Open == folderType) {
flags += Shell32.SHGFI_OPENICON;
}
if (IconSize.Small == size) {
flags += Shell32.SHGFI_SMALLICON;
} else {
flags += Shell32.SHGFI_LARGEICON;
}
Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
Shell32.SHGetFileInfo(name,
Shell32.FILE_ATTRIBUTE_DIRECTORY,
ref shfi,
(uint)System.Runtime.InteropServices.Marshal.SizeOf(shfi),
flags);
System.Drawing.Icon.FromHandle(shfi.hIcon);
System.Drawing.Icon icon = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shfi.hIcon).Clone();
User32.DestroyIcon(shfi.hIcon);
return icon;
}
}
}
public class Shell32
{
public const int MAX_PATH = 256;
[StructLayout(LayoutKind.Sequential)]
public struct SHITEMID
{
public ushort cb;
[MarshalAs(UnmanagedType.LPArray)]
public byte[] abID;
}
[StructLayout(LayoutKind.Sequential)]
public struct ITEMIDLIST
{
public SHITEMID mkid;
}
[StructLayout(LayoutKind.Sequential)]
public struct BROWSEINFO
{
public IntPtr hwndOwner;
public IntPtr pidlRoot;
public IntPtr pszDisplayName;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpszTitle;
public uint ulFlags;
public IntPtr lpfn;
public int lParam;
public IntPtr iImage;
}
public const uint BIF_RETURNONLYFSDIRS = 0x0001;
public const uint BIF_DONTGOBELOWDOMAIN = 0x0002;
public const uint BIF_STATUSTEXT = 0x0004;
public const uint BIF_RETURNFSANCESTORS = 0x0008;
public const uint BIF_EDITBOX = 0x0010;
public const uint BIF_VALIDATE = 0x0020;
public const uint BIF_NEWDIALOGSTYLE = 0x0040;
public const uint BIF_USENEWUI = (BIF_NEWDIALOGSTYLE | BIF_EDITBOX);
public const uint BIF_BROWSEINCLUDEURLS = 0x0080;
public const uint BIF_BROWSEFORCOMPUTER = 0x1000;
public const uint BIF_BROWSEFORPRINTER = 0x2000;
public const uint BIF_BROWSEINCLUDEFILES = 0x4000;
public const uint BIF_SHAREABLE = 0x8000;
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
public const int NAMESIZE = 80;
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NAMESIZE)]
public string szTypeName;
};
public const uint SHGFI_ICON = 0x000000100;
public const uint SHGFI_DISPLAYNAME = 0x000000200;
public const uint SHGFI_TYPENAME = 0x000000400;
public const uint SHGFI_ATTRIBUTES = 0x000000800;
public const uint SHGFI_ICONLOCATION = 0x000001000;
public const uint SHGFI_EXETYPE = 0x000002000;
public const uint SHGFI_SYSICONINDEX = 0x000004000;
public const uint SHGFI_LINKOVERLAY = 0x000008000;
public const uint SHGFI_SELECTED = 0x000010000;
public const uint SHGFI_ATTR_SPECIFIED = 0x000020000;
public const uint SHGFI_LARGEICON = 0x000000000;
public const uint SHGFI_SMALLICON = 0x000000001;
public const uint SHGFI_OPENICON = 0x000000002;
public const uint SHGFI_SHELLICONSIZE = 0x000000004;
public const uint SHGFI_PIDL = 0x000000008;
public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
public const uint SHGFI_ADDOVERLAYS = 0x000000020;
public const uint SHGFI_OVERLAYINDEX = 0x000000040;
public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
[DllImport("Shell32.dll")]
public static extern IntPtr SHGetFileInfo(
string pszPath,
uint dwFileAttributes,
ref SHFILEINFO psfi,
uint cbFileInfo,
uint uFlags
);
}
static class User32
{
[DllImport("User32.dll")]
public static extern int DestroyIcon(IntPtr hIcon);
}
}