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

发布于 2024-10-09 02:41:13 字数 579 浏览 0 评论 0原文

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

怀疑其原因是当我调用 Bitmap.FromHbitmap 将 hbitmap 转换为位图时透明度丢失。是否可以在不失去透明度的情况下进行转换?我什至不确定这是否是问题所在。我能找到的唯一参考是对 关于 IShellItemImageFactory 的问题 上面说

“API 有时会返回位图 使用预乘 alpha 和 有时使用正常的 alpha"

有没有办法获得没有黑色背景的图标,或者当没有缩略图时我应该坚持使用 Icon.ExtractAssociatedIcon

I'm trying to extract thumbnail or icon if the thumbnail is not available from a file or folder like windows explorer. I'm using IShellItemImageFactory and when the thumbnail is present it works nicely. However, if the file does not have a thumbnail the icon returned by the method has a black background.

Is suspect the reason for this is that the transparency is lost when I call Bitmap.FromHbitmap to convert the hbitmap to bitmap. Is it possible to convert without losing the transparency? I'm not even sure if that's the problem or not. The only reference that I could find is a comment to question about IShellItemImageFactory which says that

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

Is there any way to get the icon without black background or should I just stick to Icon.ExtractAssociatedIcon when there is no thumbnail?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

可遇━不可求 2024-10-16 02:41:13

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

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

I use the following code, not sure if it transparent backgrounds are supported but you could give it a try:

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);
无可置疑 2024-10-16 02:41:13

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

The bitmap returned has alpha. It's 32bits and the last 8 bits are alpha. I'm not sure what happens to this in your call to Bitmap.FromHbitmap, but you should probably know that even if the alpha is copied correctly (probably is), you may not use it later. If you ignore the alpha, you'll see a black box.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文