Convert System.Drawing.Icon to System.Media.ImageSource

I have an IntPtr marshaled at an unmanaged / managed border that matches the Handle icon. Converting it to an icon is trivial with the FromHandle () method, and this has been satisfactory until recently.

Basically, I now have quite a few oddities when the MTA / STA tandem that I played to support WinForm in violation of the main (WPF-tastic) application interface is too fragile to stick to. So, WinForm should go.

So, how can I get the IconSource version of the icon?

Notice I tried ImageSourceConverter to no avail.

As an aside, I can get a basic resource for some, but not all, icons, and they generally exist outside of my application assembly (in fact, they often exist in unmanaged dll's).

+35
c # windows winforms wpf
Jul 14 '09 at 20:03
source share
7 answers

Try the following:

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

UPDATE Include the Alex sentence and make it an extension method:

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

Then you can do:

 ImageSource wpfBitmap = img.ToImageSource(); 
+46
Jul 14 '09 at 20:23
source share

A simple way to transform without creating any additional objects:

  public static ImageSource ToImageSource(this Icon icon) { ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon( icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); return imageSource; } 
+68
Jul 05 2018-11-11T00:
source share

When using one-time threads, it is almost always recommended to use “use” blocks to force the release of resources.

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

Where icon is the source of System.Drawing.Icon, and this.TargetWindow is the target System.Windows.Window.

+10
Oct 27 '10 at 8:30
source share
 MemoryStream iconStream = new MemoryStream(); myForm.Icon.Save(iconStream); iconStream.Seek(0, SeekOrigin.Begin); _wpfForm.Icon = System.Windows.Media.Imaging.BitmapFrame.Create(iconStream); 
+9
Aug 28 '09 at 14:35
source share

Taking from the foregoing, this created the highest quality icons for yourself. Loading icons from an array of bytes. I use cache because if you do not, you will get a remote exception when you delete the memory stream.

  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); } } 
+1
Jul 04 '16 at 18:52
source share

Somehow a similar example, only configured from cases of developers ...

  [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 
0
May 9 '16 at 12:39
source share

There is a very simple solution to this problem.

Steps:

(1) add the image to the resources in explorer explorer → resources.resx (2) edit the image properties inside the "Resources" directory in the solution explorer and change "Set action" to "Resource"

In xaml add the following ...

Icon = "resources / image name" (where "image name" is the name of the image that you added to the resources - see point (1).

-2
Sep 22 '15 at 9:53 on
source share



All Articles