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

发布于 2024-08-03 00:00:51 字数 741 浏览 7 评论 0原文

目前,我通过调用 SHGetFileInfo 获取本机图标。然后,我使用以下代码将其转换为位图。位图最终以 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);
        }

Currently I'm getting a native icon by calling SHGetFileInfo. Then, I'm converting it to a bitmap using the following code. The Bitmap eventually gets displayed in the WPF form.

Is there a faster way to do the same thing?

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

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

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

发布评论

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

评论(5

德意的啸 2024-08-10 00:00:51

怎么样:

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

How about something like:

var icon = System.Drawing.Icon.ExtractAssociatedIcon(fileName);
var bmp = icon.ToBitmap()
埖埖迣鎅 2024-08-10 00:00:51
using System.Windows.Interop;

...

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

...

ImageSource img = Imaging.CreateBitmapSourceFromHIcon(
    shinfo.hIcon,
    new Int32Rect(0,0,i.Width, i.Height),
    BitmapSizeOptions.FromEmptyOptions());
温柔一刀 2024-08-10 00:00:51

合并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;
        }

和互操作类:

using System;
using System.Runtime.InteropServices;
public static class Interop
  {
    /// <summary>Maximal Length of unmanaged Windows-Path-strings</summary>
    private const int MAX_PATH = 260;
    /// <summary>Maximal Length of unmanaged Typename</summary>
    private const int MAX_TYPE = 80;


    [Flags]
    public enum SHGFI : int
    {
      /// <summary>get icon</summary>
      Icon = 0x000000100,
      /// <summary>get display name</summary>
      DisplayName = 0x000000200,
      /// <summary>get type name</summary>
      TypeName = 0x000000400,
      /// <summary>get attributes</summary>
      Attributes = 0x000000800,
      /// <summary>get icon location</summary>
      IconLocation = 0x000001000,
      /// <summary>return exe type</summary>
      ExeType = 0x000002000,
      /// <summary>get system icon index</summary>
      SysIconIndex = 0x000004000,
      /// <summary>put a link overlay on icon</summary>
      LinkOverlay = 0x000008000,
      /// <summary>show icon in selected state</summary>
      Selected = 0x000010000,
      /// <summary>get only specified attributes</summary>
      Attr_Specified = 0x000020000,
      /// <summary>get large icon</summary>
      LargeIcon = 0x000000000,
      /// <summary>get small icon</summary>
      SmallIcon = 0x000000001,
      /// <summary>get open icon</summary>
      OpenIcon = 0x000000002,
      /// <summary>get shell size icon</summary>
      ShellIconSize = 0x000000004,
      /// <summary>pszPath is a pidl</summary>
      PIDL = 0x000000008,
      /// <summary>use passed dwFileAttribute</summary>
      UseFileAttributes = 0x000000010,
      /// <summary>apply the appropriate overlays</summary>
      AddOverlays = 0x000000020,
      /// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary>
      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);
  }

Combining Krzysztof Kowalczyk answer with some googling, i made up this:

Method:

/*
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;
        }

and Interop class:

using System;
using System.Runtime.InteropServices;
public static class Interop
  {
    /// <summary>Maximal Length of unmanaged Windows-Path-strings</summary>
    private const int MAX_PATH = 260;
    /// <summary>Maximal Length of unmanaged Typename</summary>
    private const int MAX_TYPE = 80;


    [Flags]
    public enum SHGFI : int
    {
      /// <summary>get icon</summary>
      Icon = 0x000000100,
      /// <summary>get display name</summary>
      DisplayName = 0x000000200,
      /// <summary>get type name</summary>
      TypeName = 0x000000400,
      /// <summary>get attributes</summary>
      Attributes = 0x000000800,
      /// <summary>get icon location</summary>
      IconLocation = 0x000001000,
      /// <summary>return exe type</summary>
      ExeType = 0x000002000,
      /// <summary>get system icon index</summary>
      SysIconIndex = 0x000004000,
      /// <summary>put a link overlay on icon</summary>
      LinkOverlay = 0x000008000,
      /// <summary>show icon in selected state</summary>
      Selected = 0x000010000,
      /// <summary>get only specified attributes</summary>
      Attr_Specified = 0x000020000,
      /// <summary>get large icon</summary>
      LargeIcon = 0x000000000,
      /// <summary>get small icon</summary>
      SmallIcon = 0x000000001,
      /// <summary>get open icon</summary>
      OpenIcon = 0x000000002,
      /// <summary>get shell size icon</summary>
      ShellIconSize = 0x000000004,
      /// <summary>pszPath is a pidl</summary>
      PIDL = 0x000000008,
      /// <summary>use passed dwFileAttribute</summary>
      UseFileAttributes = 0x000000010,
      /// <summary>apply the appropriate overlays</summary>
      AddOverlays = 0x000000020,
      /// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary>
      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);
  }

source

随风而去 2024-08-10 00:00:51

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

            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) 的情况
  • 确保使用 win32 api DestroyIcon () 如果它来自 SHGetFileInfo()

Thomas's code could be simplified even more. Here's the full code with additional error checking:

            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;

The difference is:

  • no need to create Icon object
  • make sure to handle a case where iconHandle is 0 (IntPtr.Zero) by e.g. returning some pre-defined ImageSource object
  • make sure to use win32 api DestroyIcon() if it comes from SHGetFileInfo()
Saygoodbye 2024-08-10 00:00:51

我相信有更简单(更易于管理)的方法来解决这里强调的问题。
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);

I belive there's simpler (more managed) way of solving this hilighted here.
http://www.pchenry.com/Home/tabid/36/EntryID/193/Default.aspx

The crux is of the solution is here.

System.Drawing.Icon formIcon = IconsInWPF.Properties.Resources.Habs;
MemoryStream stream = new MemoryStream();
formIcon.Save(stream);
this.Icon = BitmapFrame.Create(stream);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文