Получить значки программ

#wpf #vb.net

Вопрос:

Я создаю приложение, похожее на проводник, для просмотра файлов, хранящихся на моем компьютере. Мое приложение будет отображаться в режиме «Значок». Вопрос в следующем: как отобразить значок exe-файла?

Ответ №1:

Есть несколько способов сделать это. Самым простым, вероятно, является добавление ссылки на System.Drawing Icon.ExtractAssociatedIcon метод и использование его преимуществ:

 public static ImageSource GetIcon(string fileName)
{
    Icon icon = Icon.ExtractAssociatedIcon(fileName);
    return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
                icon.Handle, 
                new Int32Rect(icon.Width, icon.Height),
                BitmapSizeOptions.FromEmptyOptions());
}
 

Другой вариант, если вы не хотите его использовать System.Drawing , — это получить значок из SHGetFileInfo API. Это сложнее, но и гораздо более гибко; например, вы можете получить значок несуществующего файла на основе расширения (конечно, для исполняемого файла это не очень полезно, так как он вернет значок по умолчанию для исполняемых файлов).

 public static ImageSource GetIcon(string path, bool smallIcon, bool isDirectory)
{
    // SHGFI_USEFILEATTRIBUTES takes the file name and attributes into account if it doesn't exist
    uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES;
    if (smallIcon)
        flags |= SHGFI_SMALLICON;

    uint attributes = FILE_ATTRIBUTE_NORMAL;
    if (isDirectory)
        attributes |= FILE_ATTRIBUTE_DIRECTORY;

    SHFILEINFO shfi;
    if (0 != SHGetFileInfo(
                path,
                attributes,
                out shfi,
                (uint)Marshal.SizeOf(typeof(SHFILEINFO)),
                flags))
    {
        return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
                    shfi.hIcon, 
                    Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions());
    }
    return null;
}

[StructLayout(LayoutKind.Sequential)]
private struct SHFILEINFO
{
    public IntPtr hIcon;
    public int iIcon;
    public uint dwAttributes;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string szDisplayName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
    public string szTypeName;
}

    [DllImport("shell32")]
    private static extern int SHGetFileInfo(string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint flags);

private const uint FILE_ATTRIBUTE_READONLY = 0x00000001;
private const uint FILE_ATTRIBUTE_HIDDEN = 0x00000002;
private const uint FILE_ATTRIBUTE_SYSTEM = 0x00000004;
private const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
private const uint FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
private const uint FILE_ATTRIBUTE_DEVICE = 0x00000040;
private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
private const uint FILE_ATTRIBUTE_TEMPORARY = 0x00000100;
private const uint FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200;
private const uint FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400;
private const uint FILE_ATTRIBUTE_COMPRESSED = 0x00000800;
private const uint FILE_ATTRIBUTE_OFFLINE = 0x00001000;
private const uint FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000;
private const uint FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
private const uint FILE_ATTRIBUTE_VIRTUAL = 0x00010000;

private const uint SHGFI_ICON = 0x000000100;     // get icon
private const uint SHGFI_DISPLAYNAME = 0x000000200;     // get display name
private const uint SHGFI_TYPENAME = 0x000000400;     // get type name
private const uint SHGFI_ATTRIBUTES = 0x000000800;     // get attributes
private const uint SHGFI_ICONLOCATION = 0x000001000;     // get icon location
private const uint SHGFI_EXETYPE = 0x000002000;     // return exe type
private const uint SHGFI_SYSICONINDEX = 0x000004000;     // get system icon index
private const uint SHGFI_LINKOVERLAY = 0x000008000;     // put a link overlay on icon
private const uint SHGFI_SELECTED = 0x000010000;     // show icon in selected state
private const uint SHGFI_ATTR_SPECIFIED = 0x000020000;     // get only specified attributes
private const uint SHGFI_LARGEICON = 0x000000000;     // get large icon
private const uint SHGFI_SMALLICON = 0x000000001;     // get small icon
private const uint SHGFI_OPENICON = 0x000000002;     // get open icon
private const uint SHGFI_SHELLICONSIZE = 0x000000004;     // get shell size icon
private const uint SHGFI_PIDL = 0x000000008;     // pszPath is a pidl
private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;     // use passed dwFileAttribute
 

Еще одним преимуществом этого подхода является то, что он также может получить значок для каталога (см. Последнее изменение в коде), что невозможно с помощью Icon.ExtractAssociatedIcon

Комментарии:

1. Какая функция? Икона. ЭкстрааСсоциироваНный словарь? Это не часть самого WPF, но оно находится в .NET Framework. Система. Рисунок — это просто оболочка для GDI

2. Я не могу импортировать систему. Пространство имен рисования в WPF, как мне получить класс значков?

3. Как я уже сказал в своем ответе, вам нужно добавить ссылку на System.Drawing сборку (вам также, конечно, нужно импортировать пространство имен).