Convert System.Drawing.Icon to System.Media.ImageSource
Try this:
Icon img;
Bitmap bitmap = img.ToBitmap();
IntPtr hBitmap = bitmap.GetHbitmap();
ImageSource wpfBitmap =
Imaging.CreateBitmapSourceFromHBitmap(
hBitmap, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
UPDATE: Incorporating Alex's suggestion and making 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();
How to convert icon (Bitmap) to ImageSource?
The solution suggested by Farhan Anam will work, but it's not ideal: the icon is loaded from a file, converted to a bitmap, saved to a stream and reloaded from the stream. That's quite inefficient.
Another approach is to use the System.Windows.Interop.Imaging
class and its CreateBitmapSourceFromHIcon
method:
private ImageSource IconToImageSource(System.Drawing.Icon icon)
{
return Imaging.CreateBitmapSourceFromHIcon(
icon.Handle,
new Int32Rect(0, 0, icon.Width, icon.Height),
BitmapSizeOptions.FromEmptyOptions());
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
using (var ico = System.Drawing.Icon.ExtractAssociatedIcon(@"C:\WINDOWS\system32\notepad.exe"))
{
image1.Source = IconToImageSource(ico);
}
}
Note the using
block to dispose the original icon after you converted it. Not doing this will cause handle leaks.
How to cast a Window's icon to BitmapImage
The problem is that the cast is not happening (bi is null after executing this line) and I'm sure that the _window.Icon is not null
It's not null, but it's probably not a BitmapImage
. The Window.Icon
is of type ImageSource
, from which BitmapImage
is derived. When you set the icon in XAML, the type of the image is typically System.Windows.Media.Imaging.BitmapFrameDecode
, which is an internal class derived from BitmapFrame
; so it's not a BitmapImage
, which is why the cast fails.
EDIT: if you just need to convert the icon to a System.Drawing.Bitmap
, you don't need a BitmapImage
; a BitmapSource
is enough.
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)_window.Icon));
using (var stream = new MemoryStream()))
{
encoder.Save(stream);
stream.Position = 0; // rewind the stream
var bitmap = (System.Drawing.Bitmap)System.Drawing.Image.FromStream(stream);
var icon = System.Drawing.Icon.FromHandle(bitmap.GetHicon());
}
Display Icon in WPF Image
Icons get no love in the .NET framework. You'll have to use Icon.Save() to save the icon you got into a MemoryStream. Which allows you to use the IconBitmapDecoder constructor that takes a stream.
using XAML to bind to a System.Drawing.Image into a System.Windows.Image control
Found a way I'm happy with. Using Reed Copsey's pointer and this tutorial I've wrapped the code as a IValueConverter
.
Here's the converter from System.Drawing.Image
to System.Windows.Media.ImageSource
;
using System;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Windows.Data;
namespace System.Windows.Media
{
/// <summary>
/// One-way converter from System.Drawing.Image to System.Windows.Media.ImageSource
/// </summary>
[ValueConversion(typeof(System.Drawing.Image), typeof(System.Windows.Media.ImageSource))]
public class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
// empty images are empty...
if (value == null) { return null; }
var image = (System.Drawing.Image)value;
// Winforms Image we want to get the WPF Image from...
var bitmap = new System.Windows.Media.Imaging.BitmapImage();
bitmap.BeginInit();
MemoryStream memoryStream = new MemoryStream();
// Save to a memory stream...
image.Save(memoryStream, ImageFormat.Bmp);
// Rewind the stream...
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
bitmap.StreamSource = memoryStream;
bitmap.EndInit();
return bitmap;
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return null;
}
}
}
Then you need to bring the image converter into XAML as a resource;
xmlns:med="clr-namespace:System.Windows.Media"
...
<ListView.Resources>
<med:ImageConverter x:Key="imageConverter" />
</ListView.Resources>
Then you can use it in XAML to bind directly to the Image, using the new converter;
<Image Source="{ Binding Path=Image, Converter={StaticResource imageConverter} }" />
Related Topics
Send Smtp Email Using System.Net.Mail via Exchange Online (Office 365)
How to Show File Copy Progress Using Fileinfo.Copyto() in .Net
Entity Framework/Sql2008 - How to Automatically Update Lastmodified Fields for Entities
Convert Base Class to Derived Class
Is Endinvoke() Optional, Sort-Of Optional, or Definitely Not Optional
How to Initialize a List<T> to a Given Size (As Opposed to Capacity)
Should You Declare Methods Using Overloads or Optional Parameters in C# 4.0
What Is the Fastest Way to Combine Two Xml Files into One
JSON String to CSV and CSV to JSON Conversion in C#
Creating Delegates Manually VS Using Action/Func Delegates
Could Not Load File or Assembly 'Microsoft.Reportviewer.Common, Version=11.0.0.0
Check If the Current User Is Administrator
Access to Foreach Variable in Closure Warning
I Didn't Find "Zipfile" Class in the "System.Io.Compression" Namespace
Lock (Monitor) Internal Implementation in .Net
Visual Studio Build Fails: Unable to Copy Exe-File from Obj\Debug to Bin\Debug