c# - 从 C# 文件中提取缩略图和图标

标签 c# winapi shell com thumbnails

如果缩略图无法从文件或文件夹(如 Windows 资源管理器)中获得,我将尝试提取缩略图或图标。我正在使用 IShellItemImageFactory 并且当缩略图存在时它​​工作得很好。但是,如果文件没有缩略图,则该方法返回的图标具有黑色背景。

我怀疑这是因为当我调用 Bitmap.FromHbitmap 将 hbitmap 转换为位图时透明度丢失了。是否可以在不失去透明度的情况下进行转换?我什至不确定这是否是问题所在。我能找到的唯一引用是对 question about IShellItemImageFactory 的评论上面写着

"the API sometimes returns bitmaps that use pre-multiplied alpha and sometimes ones that use normal alpha"

有什么方法可以让图标没有黑色背景,或者我应该在没有缩略图的情况下坚持 Icon.ExtractAssociatedIcon 吗?

最佳答案

我使用了下面的代码,不确定是否支持透明背景,但你可以试一试:

private const uint SHGFI_ICON           = 0x100;
private const uint SHGFI_LARGEICON      = 0x0;
private const uint SHGFI_SMALLICON      = 0x1;
private const uint SHGFI_DISPLAYNAME    = 0x00000200;
private const uint SHGFI_TYPENAME       = 0x400;

public static Icon GetSmallFileIcon(this FileInfo file)
{
    if (file.Exists)
    {
        SHFILEINFO shFileInfo = new SHFILEINFO();
        SHGetFileInfo(file.FullName, 0, ref shFileInfo, (uint)Marshal.SizeOf(shFileInfo), SHGFI_ICON | SHGFI_SMALLICON);

        return Icon.FromHandle(shFileInfo.hIcon);
    }
    else return SystemIcons.WinLogo;
}

public static Icon GetSmallFileIcon(string fileName)
{
    return GetSmallFileIcon(new FileInfo(fileName));
}

public static Icon GetLargeFileIcon(this FileInfo file)
{
    if (file.Exists)
    {
        SHFILEINFO shFileInfo = new SHFILEINFO();
        SHGetFileInfo(file.FullName, 0, ref shFileInfo, (uint)Marshal.SizeOf(shFileInfo), SHGFI_ICON | SHGFI_LARGEICON);

        return Icon.FromHandle(shFileInfo.hIcon);
    }
    else return SystemIcons.WinLogo;
}

public static Icon GetLargeFileIcon(string fileName)
{
    return GetLargeFileIcon(new FileInfo(fileName));
}

[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
    public SHFILEINFO(bool b)
    {
        hIcon = IntPtr.Zero; iIcon = IntPtr.Zero; dwAttributes = 0; szDisplayName = ""; szTypeName = "";
    }

    public IntPtr hIcon;
    public IntPtr iIcon;
    public uint dwAttributes;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string szDisplayName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
    public string szTypeName;
};


[DllImport("shell32.dll")]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

关于c# - 从 C# 文件中提取缩略图和图标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4510583/

相关文章:

winapi - 使用 SetWindowText() 函数添加新行

linux - 在 linux 中合并两个文件并忽略任何重复

linux - 使用 sed 替换 bash 文件中的变量 - 输出滞后

shell - 如何在 Bourne shell 的变量中存储带引号的字符串列表? (没有 Bash 数组)

C# 动态 ExpandoObject 数组

c# - 如何获取字段的自定义属性值?

C# 如何调整来自另一个类的表单中的文本框属性?

c++ - 我的绘画代码消耗了太多内存(为了更清楚而重新措辞)

c# - 如何使用 XDocument 获取值(value)

c++ - 找出哪个进程对 USB 设备句柄具有独占锁