获取给定扩展程序的图标

Ami*_*shk 26 c#

我知道我可以使用提取文件的图标

using (System.Drawing.Icon sysicon = System.Drawing.Icon.ExtractAssociatedIcon(filePath))
{
    icon = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
        sysicon.Handle,
        System.Windows.Int32Rect.Empty,
        System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}
Run Code Online (Sandbox Code Playgroud)

但是,如果没有文件,我怎么能获得给定扩展名的图标?

SLa*_*aks 36

使用GetFileIcon从法从保罗·英格尔斯CodeProject上的文章,并通过.ext作为name参数.

GetFileIcon方法是本机的包装器,SHGetFileInfo并在此处复制以供说明:

public static System.Drawing.Icon GetFileIcon(string name, IconSize size, 
                                              bool linkOverlay)
{
    Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
    uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES;

    if (true == linkOverlay) flags += Shell32.SHGFI_LINKOVERLAY;


    /* Check the size specified for return. */
    if (IconSize.Small == size)
    {
        flags += Shell32.SHGFI_SMALLICON ; // include the small icon flag
    } 
    else 
    {
        flags += Shell32.SHGFI_LARGEICON ;  // include the large icon flag
    }

    Shell32.SHGetFileInfo( name, 
        Shell32.FILE_ATTRIBUTE_NORMAL, 
        ref shfi, 
        (uint) System.Runtime.InteropServices.Marshal.SizeOf(shfi), 
        flags );


    // Copy (clone) the returned icon to a new object, thus allowing us 
    // to call DestroyIcon immediately
    System.Drawing.Icon icon = (System.Drawing.Icon)
                         System.Drawing.Icon.FromHandle(shfi.hIcon).Clone();
    User32.DestroyIcon( shfi.hIcon ); // Cleanup
    return icon;
}
Run Code Online (Sandbox Code Playgroud)

  • 工作频率高达32x32像素...不太适合......好吧,这些天不再需要了 (4认同)
  • +1推理fu和正确的答案. (2认同)

ast*_*tef 23

下面的代码也基于Paul Ingles解决方案,但是:

  • 可用于WPF(ImageSource而不是Icon)
  • 有简单的缓存
  • 删除了所有与目录相关的东西(在我的情况下我只有文件)
  • 使用R#技巧进行重构,并使用单类简单API进行包装

我测试过它Windows 7Windows XP SP3,它的工作原理与任何字符串作为预期fileName.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;

/// <summary>
/// Internals are mostly from here: http://www.codeproject.com/Articles/2532/Obtaining-and-managing-file-and-folder-icons-using
/// Caches all results.
/// </summary>
public static class IconManager
{
    private static readonly Dictionary<string, ImageSource> _smallIconCache = new Dictionary<string, ImageSource>();
    private static readonly Dictionary<string, ImageSource> _largeIconCache = new Dictionary<string, ImageSource>();
    /// <summary>
    /// Get an icon for a given filename
    /// </summary>
    /// <param name="fileName">any filename</param>
    /// <param name="large">16x16 or 32x32 icon</param>
    /// <returns>null if path is null, otherwise - an icon</returns>
    public static ImageSource FindIconForFilename(string fileName, bool large)
    {
        var extension = Path.GetExtension(fileName);
        if (extension == null)
            return null;
        var cache = large ? _largeIconCache : _smallIconCache;
        ImageSource icon;
        if (cache.TryGetValue(extension, out icon))
            return icon;
        icon = IconReader.GetFileIcon(fileName, large ? IconReader.IconSize.Large : IconReader.IconSize.Small, false).ToImageSource();
        cache.Add(extension, icon);
        return icon;
    }
    /// <summary>
    /// http://stackoverflow.com/a/6580799/1943849
    /// </summary>
    static ImageSource ToImageSource(this Icon icon)
    {
        var imageSource = Imaging.CreateBitmapSourceFromHIcon(
            icon.Handle,
            Int32Rect.Empty,
            BitmapSizeOptions.FromEmptyOptions());
        return imageSource;
    }
    /// <summary>
    /// Provides static methods to read system icons for both folders and files.
    /// </summary>
    /// <example>
    /// <code>IconReader.GetFileIcon("c:\\general.xls");</code>
    /// </example>
    static class IconReader
    {
        /// <summary>
        /// Options to specify the size of icons to return.
        /// </summary>
        public enum IconSize
        {
            /// <summary>
            /// Specify large icon - 32 pixels by 32 pixels.
            /// </summary>
            Large = 0,
            /// <summary>
            /// Specify small icon - 16 pixels by 16 pixels.
            /// </summary>
            Small = 1
        }
        /// <summary>
        /// Returns an icon for a given file - indicated by the name parameter.
        /// </summary>
        /// <param name="name">Pathname for file.</param>
        /// <param name="size">Large or small</param>
        /// <param name="linkOverlay">Whether to include the link icon</param>
        /// <returns>System.Drawing.Icon</returns>
        public static Icon GetFileIcon(string name, IconSize size, bool linkOverlay)
        {
            var shfi = new Shell32.Shfileinfo();
            var flags = Shell32.ShgfiIcon | Shell32.ShgfiUsefileattributes;
            if (linkOverlay) flags += Shell32.ShgfiLinkoverlay;
            /* Check the size specified for return. */
            if (IconSize.Small == size)
                flags += Shell32.ShgfiSmallicon;
            else
                flags += Shell32.ShgfiLargeicon;
            Shell32.SHGetFileInfo(name,
                Shell32.FileAttributeNormal,
                ref shfi,
                (uint)Marshal.SizeOf(shfi),
                flags);
            // Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly
            var icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone();
            User32.DestroyIcon(shfi.hIcon);     // Cleanup
            return icon;
        }
    }
    /// <summary>
    /// Wraps necessary Shell32.dll structures and functions required to retrieve Icon Handles using SHGetFileInfo. Code
    /// courtesy of MSDN Cold Rooster Consulting case study.
    /// </summary>
    static class Shell32
    {
        private const int MaxPath = 256;
        [StructLayout(LayoutKind.Sequential)]
        public struct Shfileinfo
        {
            private const int Namesize = 80;
            public readonly IntPtr hIcon;
            private readonly int iIcon;
            private readonly uint dwAttributes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxPath)]
            private readonly string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Namesize)]
            private readonly string szTypeName;
        };
        public const uint ShgfiIcon = 0x000000100;     // get icon
        public const uint ShgfiLinkoverlay = 0x000008000;     // put a link overlay on icon
        public const uint ShgfiLargeicon = 0x000000000;     // get large icon
        public const uint ShgfiSmallicon = 0x000000001;     // get small icon
        public const uint ShgfiUsefileattributes = 0x000000010;     // use passed dwFileAttribute
        public const uint FileAttributeNormal = 0x00000080;
        [DllImport("Shell32.dll")]
        public static extern IntPtr SHGetFileInfo(
            string pszPath,
            uint dwFileAttributes,
            ref Shfileinfo psfi,
            uint cbFileInfo,
            uint uFlags
            );
    }
    /// <summary>
    /// Wraps necessary functions imported from User32.dll. Code courtesy of MSDN Cold Rooster Consulting example.
    /// </summary>
    static class User32
    {
        /// <summary>
        /// Provides access to function required to delete handle. This method is used internally
        /// and is not required to be called separately.
        /// </summary>
        /// <param name="hIcon">Pointer to icon handle.</param>
        /// <returns>N/A</returns>
        [DllImport("User32.dll")]
        public static extern int DestroyIcon(IntPtr hIcon);
    }
}
Run Code Online (Sandbox Code Playgroud)


Maj*_*jor 9

它可以做得更简单:

System.Drawing.Icon.ExtractAssociatedIcon("<fullPath>");
Run Code Online (Sandbox Code Playgroud)

重要说明:如果文件不存在,它将抛出异常,因此值得添加验证.

  • 添加说明文件必须_exist_,但它不必_valid_ - `Icon.ExtractAssociatedIcon(@"c:\temp\this_is_actually_a_text_file.xls");` 将返回正确的 Excel 图标,即使文件只是一个文本文件。 (2认同)
  • 还有一点需要注意的是,虽然 [docs](https://docs.microsoft.com/en-us/dotnet/api/system.drawing.icon.extractassociatedicon?view=netframework-4.8) 表明 `fullPath`是一个 UNC 路径,在我的测试中,即使`File.Exists()` 给了它们a-ok,调用也会抛出位于网络共享上的文件。 (2认同)