将System.Drawing.Icon转换为System.Media.ImageSource

我有一个IntPtr封送在非托pipe/pipe理的边界对应的图标句柄。 通过FromHandle()方法将它转换为一个Icon是很简单的,直到最近这一点都是令人满意的。

基本上,我现在已经有足够的线程奇怪了,我一直在玩的MTA / STA舞蹈,以保持托pipe的WinForm不会破坏应用程序的主要(WPF-tastic)UI太脆弱,不能坚持。 所以WinForm已经走了。

那么,我怎样才能得到一个图标的ImageSource版本?

请注意,我试过ImageSourceConverter无济于事。

顺便说一下,我可以获取一些但不是所有涉及的图标的底层资源,它们通常存在于我的应用程序的程序集之外(事实上,它们通常存在于非​​托pipe的dll中)。

尝试这个:

Icon img; Bitmap bitmap = img.ToBitmap(); IntPtr hBitmap = bitmap.GetHbitmap(); ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap( hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 

更新 :纳入亚历克斯的build议,并使其成为一种扩展方法:

 internal static class IconUtilities { [DllImport("gdi32.dll", SetLastError = true)] private static extern bool DeleteObject(IntPtr hObject); public static ImageSource ToImageSource(this Icon icon) { Bitmap bitmap = icon.ToBitmap(); IntPtr hBitmap = bitmap.GetHbitmap(); ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap( hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); if (!DeleteObject(hBitmap)) { throw new Win32Exception(); } return wpfBitmap; } } 

那你可以这样做:

 ImageSource wpfBitmap = img.ToImageSource(); 

简单的转换方法,不创build任何额外的对象

  public static ImageSource ToImageSource(this Icon icon) { ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon( icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); return imageSource; } 

使用一次性stream时,几乎总是build议使用“使用”块来强制正确释放资源。

 using (MemoryStream iconStream = new MemoryStream()) { icon.Save(iconStream); iconStream.Seek(0, SeekOrigin.Begin); this.TargetWindow.Icon = System.Windows.Media.Imaging.BitmapFrame.Create(iconStream); } 

其中icon是源System.Drawing.Icon,而this.TargetWindow是目标System.Windows.Window。

 MemoryStream iconStream = new MemoryStream(); myForm.Icon.Save(iconStream); iconStream.Seek(0, SeekOrigin.Begin); _wpfForm.Icon = System.Windows.Media.Imaging.BitmapFrame.Create(iconStream); 

从一些以上这为我自己创造了最高质量的图标。 从字节数组中加载图标。 我使用caching加载,因为如果你不这样做,当你处理内存stream时,你会得到一个处置的exception。

  internal static ImageSource ToImageSource(this byte[] iconBytes) { if (iconBytes == null) throw new ArgumentNullException(nameof(iconBytes)); using (var ms = new MemoryStream(iconBytes)) { return BitmapFrame.Create(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); } } 

以某种方式类似的例子,只从开发人员的用例调整…

  [DllImport("shell32.dll")] public static extern IntPtr ExtractIcon(IntPtr hInst, string file, int nIconIndex); [DllImport("user32.dll", SetLastError = true)] static extern bool DestroyIcon(IntPtr hIcon); /// <summary> /// Gets application icon from main .exe. /// </summary> /// <param name="setToObject">object to which to set up icon</param> /// <param name="bAsImageSource">true if get it as "ImageSource" (xaml technology), false if get it as "Icon" (winforms technology)</param> /// <returns>true if successful.</returns> public bool GetIcon(object setToObject, bool bAsImageSource) { String path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); path = Path.Combine(path, "yourmainexecutableName.exe"); int iIconIndex = 0; // If your application contains multiple icons, then // you could change iIconIndex here. object o2set = null; IntPtr hIcon = ExtractIcon(IntPtr.Zero, path, iIconIndex); if (hIcon == IntPtr.Zero) return false; Icon icon = (Icon)Icon.FromHandle(hIcon); if (bAsImageSource) { o2set = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( icon.ToBitmap().GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); } else { icon = (Icon)icon.Clone(); } DestroyIcon(hIcon); setToObject.GetType().GetProperty("Icon").SetValue(setToObject, o2set); return true; } //GetIcon 

这个问题有一个非常简单的解决scheme。

脚步:

(1)在解决scheme资源pipe理器中添加资源 – > resources.resx(2)在解决scheme资源pipe理器中的“Resources”目录下编辑图片属性,将“Build action”改为“Resource”

在xaml中,添加以下内容…

图标=“资源/图像名称”(其中“图像名称”是您添加到资源中的图像的名称 – 请参阅第(1)点。