c# - 有没有办法使用 C# 获取 Windows 默认文件夹图标?

标签 c#

我有一个带有文档列表的listView。我使用以下方法为每个人分配了一个图标:

private void SetDocumentIcon(ListViewItem item, FileInfo file)
{
    Icon iconForFile = Icon.ExtractAssociatedIcon(file.FullName);

    if (!documentsIconsImageList.Images.ContainsKey(file.Extension))
    {
        iconForFile = Icon.ExtractAssociatedIcon(file.FullName);
        documentsIconsImageList.Images.Add(file.Extension, iconForFile);
    }

    item.ImageKey = file.Extension;
}

我尝试对文件夹使用此方法,但失败了。据我了解,问题在于 Icon.ExtractAssociatedIcon 适用于文件而不是文件夹。那么如何提取文件夹的图标呢?

谢谢。

最佳答案

SHGetStockIconInfo是正确的做法,并且不需要添加不必要的文件 IO。它并不比 SHGetFileInfo 更复杂。

这是一个示例类,其结构与 Evk 的类类似。需要注意的一些重要事项:

  1. 当您从 SHGetStockIconInfo(甚至是 SHGetFileInfo)获取图标句柄时, native 图标必须被清理调用DestroyIcon() ,否则会造成资源泄漏。
  2. 当您使用 Icon.FromHandle() 创建图标时,该对象存储您给它的句柄并将其用于以后的操作。这意味着如果您立即调用 DestroyIcon() 然后尝试对刚刚创建的图标执行某些操作,则会导致异常。您可以通过使用 Clone() 来避免这种情况获取不依赖于原始 native 句柄的 Icon
public static class DefaultIcons
{
    private static Icon folderIcon;

    public static Icon FolderLarge => folderIcon ?? (folderIcon = GetStockIcon(SHSIID_FOLDER, SHGSI_LARGEICON));

    private static Icon GetStockIcon(uint type, uint size)
    {
        var info = new SHSTOCKICONINFO();
        info.cbSize = (uint)Marshal.SizeOf(info);

        SHGetStockIconInfo(type, SHGSI_ICON | size, ref info);

        var icon = (Icon)Icon.FromHandle(info.hIcon).Clone(); // Get a copy that doesn't use the original handle
        DestroyIcon(info.hIcon); // Clean up native icon to prevent resource leak

        return icon;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct SHSTOCKICONINFO
    {
        public uint cbSize;
        public IntPtr hIcon;
        public int iSysIconIndex;
        public int iIcon;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szPath;
    }

    [DllImport("shell32.dll")]
    public static extern int SHGetStockIconInfo(uint siid, uint uFlags, ref SHSTOCKICONINFO psii);

    [DllImport("user32.dll")]
    public static extern bool DestroyIcon(IntPtr handle);

    private const uint SHSIID_FOLDER = 0x3;
    private const uint SHGSI_ICON = 0x100;
    private const uint SHGSI_LARGEICON = 0x0;
    private const uint SHGSI_SMALLICON = 0x1;
}

关于c# - 有没有办法使用 C# 获取 Windows 默认文件夹图标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42910628/

相关文章:

C# - 添加到现有(生成的)构造函数

c# - 在 C# 中嵌套数组有更优雅的方法吗?

c# - 为什么人们说 SqlDataReader.GetXXX(i) 比 SqlDataReader[i] 快?

c# - 在使用浮点运算的多人 RTS 游戏中保持同步

c# - 为什么使用异步请求而不是使用更大的线程池?

c# - RabbitMQ 和 Web 服务

c# - Akka.net 中的 IActorRefs 太多

c# - 在我看来,什么时候应该从数据库中查询,ASP.NET MVC

c# - 不能同时旋​​转和移动

c# - 不可变类和统一应用程序 block