C# 用c语言从文件中提取缩略图和图标#

C# 用c语言从文件中提取缩略图和图标#,c#,winapi,shell,com,thumbnails,C#,Winapi,Shell,Com,Thumbnails,如果像windows资源管理器这样的文件或文件夹中没有缩略图,我会尝试提取缩略图或图标。我使用的是IShellItemImageFactory,当出现缩略图时,效果很好。但是,如果文件没有缩略图,则该方法返回的图标具有黑色背景 原因可能是调用Bitmap.FromHbitmap将hbitmap转换为位图时透明度丢失。是否可以在不丢失透明度的情况下进行转换?我甚至不确定这是否是问题所在。我能找到的唯一参考是一条评论,上面说 “API有时返回位图 使用预乘的alpha和 有时使用正常阿尔法的人“ 有

如果像windows资源管理器这样的文件或文件夹中没有缩略图,我会尝试提取缩略图或图标。我使用的是IShellItemImageFactory,当出现缩略图时,效果很好。但是,如果文件没有缩略图,则该方法返回的图标具有黑色背景

原因可能是调用
Bitmap.FromHbitmap
将hbitmap转换为位图时透明度丢失。是否可以在不丢失透明度的情况下进行转换?我甚至不确定这是否是问题所在。我能找到的唯一参考是一条评论,上面说

“API有时返回位图 使用预乘的alpha和 有时使用正常阿尔法的人“


有没有办法获得没有黑色背景的图标,或者我应该坚持使用
图标。在没有缩略图的情况下提取关联图标

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

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);

返回的位图包含alpha。它是32位,最后8位是alpha。我不确定在调用Bitmap.FromHbitmap时会发生什么情况,但您应该知道,即使正确复制了alpha(可能是),以后也可能不会使用它。如果忽略alpha,您将看到一个黑框。

谢谢您的代码片段。实际上我知道SHGetFileInfo函数。我只是想避免检查缩略图是否可用,如果不可用,则提取图标。