如何在WPF中显示Windows文件图标?

目前我通过调用SHGetFileInfo获取本机图标。 然后,我使用以下代码将其转换为位图。 Bitmap最终以WPF格式显示。

有没有更快的方法来做同样的事情?

try { using (Icon i = Icon.FromHandle(shinfo.hIcon)) { Bitmap bmp = i.ToBitmap(); MemoryStream strm = new MemoryStream(); bmp.Save(strm, System.Drawing.Imaging.ImageFormat.Png); BitmapImage bmpImage = new BitmapImage(); bmpImage.BeginInit(); strm.Seek(0, SeekOrigin.Begin); bmpImage.StreamSource = strm; bmpImage.EndInit(); return bmpImage; } } finally { Win32.DestroyIcon(hImgLarge); } 

 using System.Windows.Interop; ... using (Icon i = Icon.FromHandle(shinfo.hIcon)) { ImageSource img = Imaging.CreateBitmapSourceFromHIcon( i.Handle, new Int32Rect(0,0,i.Width, i.Height), BitmapSizeOptions.FromEmptyOptions()); } 

怎么样的:

 var icon = System.Drawing.Icon.ExtractAssociatedIcon(fileName); var bmp = icon.ToBitmap() 

结合Krzysztof Kowalczyk的回答和一些谷歌搜索,我编写了这个:

方法:

 /* using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; */ public static ImageSource GetIcon(string strPath, bool bSmall) { Interop.SHFILEINFO info = new Interop.SHFILEINFO(true); int cbFileInfo = Marshal.SizeOf(info); Interop.SHGFI flags; if (bSmall) flags = Interop.SHGFI.Icon | Interop.SHGFI.SmallIcon | Interop.SHGFI.UseFileAttributes; else flags = Interop.SHGFI.Icon | Interop.SHGFI.LargeIcon | Interop.SHGFI.UseFileAttributes; Interop.SHGetFileInfo(strPath, 256, out info, (uint)cbFileInfo, flags); IntPtr iconHandle = info.hIcon; //if (IntPtr.Zero == iconHandle) // not needed, always return icon (blank) // return DefaultImgSrc; ImageSource img = Imaging.CreateBitmapSourceFromHIcon( iconHandle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); Interop.DestroyIcon(iconHandle); return img; } 

和Interop类:

 using System; using System.Runtime.InteropServices; public static class Interop { /// Maximal Length of unmanaged Windows-Path-strings private const int MAX_PATH = 260; /// Maximal Length of unmanaged Typename private const int MAX_TYPE = 80; [Flags] public enum SHGFI : int { /// get icon Icon = 0x000000100, /// get display name DisplayName = 0x000000200, /// get type name TypeName = 0x000000400, /// get attributes Attributes = 0x000000800, /// get icon location IconLocation = 0x000001000, /// return exe type ExeType = 0x000002000, /// get system icon index SysIconIndex = 0x000004000, /// put a link overlay on icon LinkOverlay = 0x000008000, /// show icon in selected state Selected = 0x000010000, /// get only specified attributes Attr_Specified = 0x000020000, /// get large icon LargeIcon = 0x000000000, /// get small icon SmallIcon = 0x000000001, /// get open icon OpenIcon = 0x000000002, /// get shell size icon ShellIconSize = 0x000000004, /// pszPath is a pidl PIDL = 0x000000008, /// use passed dwFileAttribute UseFileAttributes = 0x000000010, /// apply the appropriate overlays AddOverlays = 0x000000020, /// Get the index of the overlay in the upper 8 bits of the iIcon OverlayIndex = 0x000000040, } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct SHFILEINFO { public SHFILEINFO(bool b) { hIcon = IntPtr.Zero; iIcon = 0; dwAttributes = 0; szDisplayName = ""; szTypeName = ""; } public IntPtr hIcon; public int iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_TYPE)] public string szTypeName; }; [DllImport("shell32.dll", CharSet = CharSet.Auto)] public static extern int SHGetFileInfo( string pszPath, int dwFileAttributes, out SHFILEINFO psfi, uint cbfileInfo, SHGFI uFlags); [DllImport("user32.dll", SetLastError = true)] public static extern bool DestroyIcon(IntPtr hIcon); } 

资源

托马斯的代码可以更简化。 这是带有额外错误检查的完整代码:

  Interop.SHGetFileInfo(path, isFile, ref pifFileInfo); IntPtr iconHandle = pifFileInfo.hIcon; if (IntPtr.Zero == iconHandle) return DefaultImgSrc; ImageSource img = Imaging.CreateBitmapSourceFromHIcon( iconHandle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); User32.DestroyIcon(iconHandle); return img; 

不同之处是:

  • 无需创建Icon对象
  • 确保通过返回一些预定义的ImageSource对象来处理iconHandle为0(IntPtr.Zero)的情况
  • 如果它来自SHGetFileInfo(),请确保使用win32 api DestroyIcon()

我相信这里有更简单(更有管理)的解决方法。 http://www.pchenry.com/Home/tabid/36/EntryID/193/Default.aspx

问题的关键在于此。

 System.Drawing.Icon formIcon = IconsInWPF.Properties.Resources.Habs; MemoryStream stream = new MemoryStream(); formIcon.Save(stream); this.Icon = BitmapFrame.Create(stream);