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

Kev*_*ose 41 c# windows wpf winforms

我有一个IntPtr封装在一个非托管/管理边界上,对应一个Icon Handle.通过FromHandle()方法将它转换为Icon是微不足道的,直到最近才令人满意.

基本上,我已经有足够的线程怪异了,因为我一直在玩MTA/STA舞蹈以保持托管的WinForm不会破坏应用程序的主要(WPF-tastic)UI太脆弱而无法坚持.所以WinForm必须要去.

那么,我怎样才能获得Icon的ImageSource版本?

注意,我尝试过ImageSourceConverter无济于事.

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

小智 81

简单转换方法,无需创建任何额外对象:

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

        return imageSource;
    }
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案似乎比使用Imaging.CreateBitmapSourceFromHBitmap的解决方案更优雅.当Imaging可以直接从Icon句柄创建BitmapSource时,无需创建非托管位图(然后必须记住处理它). (9认同)

Ken*_* K. 52

试试这个:

Icon img;

Bitmap bitmap = img.ToBitmap();
IntPtr hBitmap = bitmap.GetHbitmap();

ImageSource wpfBitmap =
     Imaging.CreateBitmapSourceFromHBitmap(
          hBitmap, IntPtr.Zero, Int32Rect.Empty, 
          BitmapSizeOptions.FromEmptyOptions());
Run Code Online (Sandbox Code Playgroud)

更新:纳入Alex的建议并使其成为一种扩展方法:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

ImageSource wpfBitmap = img.ToImageSource();
Run Code Online (Sandbox Code Playgroud)

  • 执行此转换后,您应该在hBitmap上使用gdi32.dll中的DeleteObject(IntPtr hObject)调用来避免内存泄漏. (2认同)

小智 10

当使用一次性流时,几乎总是建议使用"使用"块来强制正确释放资源.

using (MemoryStream iconStream = new MemoryStream())
{
   icon.Save(iconStream);
   iconStream.Seek(0, SeekOrigin.Begin);

   this.TargetWindow.Icon = System.Windows.Media.Imaging.BitmapFrame.Create(iconStream);
}
Run Code Online (Sandbox Code Playgroud)

icon源System.Drawing.Icon 在哪里 ,并且this.TargetWindow是目标System.Windows.Window.


Dar*_*ren 9

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