Извлечение эскиза и значка из файла в c # - PullRequest
4 голосов
/ 22 декабря 2010

Я пытаюсь извлечь миниатюру или значок, если миниатюра недоступна из файла или папки, например проводника Windows. Я использую IShellItemImageFactory, и когда миниатюра присутствует, она работает хорошо. Однако, если у файла нет миниатюры, значок, возвращенный методом, имеет черный фон.

Есть подозрение, что причина этого в том, что прозрачность теряется, когда я вызываю Bitmap.FromHbitmap для преобразования hbitmap в растровое изображение. Можно ли конвертировать без потери прозрачности? Я даже не уверен, в этом ли проблема или нет. Единственная ссылка, которую я смог найти, - это комментарий к вопросу о IShellItemImageFactory , в котором говорится, что

"API иногда возвращает растровые изображения которые используют предварительно умноженную альфа и иногда те, которые используют нормальную альфу "

Есть ли какой-нибудь способ получить значок без черного фона или я должен просто придерживаться Icon.ExtractAssociatedIcon, когда нет миниатюры?

Ответы [ 2 ]

3 голосов
/ 22 декабря 2010

Я использую следующий код, не уверен, что он поддерживает прозрачные фоны, но вы можете попробовать:

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);
1 голос
/ 17 апреля 2011

Возвращенное растровое изображение имеет альфа. Это 32 бита, а последние 8 бит альфа. Я не уверен, что происходит с этим при вызове Bitmap.FromHbitmap, но вы, вероятно, должны знать, что даже если альфа скопирована правильно (вероятно, есть), вы не сможете использовать ее позже. Если вы проигнорируете альфу, вы увидите черный ящик.

...