返回

WPF 图标怪异问题:将 System.Drawing.Icon 转换为 System.Media.ImageSource

windows

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

问题

需要将一个来自非托管/托管边界的 IntPtr 句柄(对应于图标句柄)转换为一个 System.Media.ImageSource。这在过去通过使用 FromHandle() 方法将指针转换为图标是很简单的,但现在遇到了线程怪异问题,而之前用来防止托管 WinForm 突破应用程序主 UI(WPF)的 MTA/STA 舞蹈变得不可靠。因此,必须放弃 WinForm,那么如何获得图标的 ImageSource 版本呢?

解决方法

要将 System.Drawing.Icon 转换为 System.Media.ImageSource,需要执行以下步骤:

  1. 获取图标句柄: 从非托管/托管边界获取指向图标句柄的 IntPtr。
  2. 创建位图: 使用图标句柄创建位图。
  3. 创建 ImageSource: 使用位图创建 ImageSource。
  4. 释放资源: 释放位图和图形对象。

代码示例

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Media.Imaging;

public static class IconConverter
{
    public static ImageSource ToImageSource(this Icon icon)
    {
        Bitmap bitmap = new Bitmap(icon.Width, icon.Height);
        Graphics graphics = Graphics.FromImage(bitmap);
        graphics.DrawIcon(icon, 0, 0);

        ImageSource imageSource = Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(),
            IntPtr.Zero,
            Int32Rect.Empty,
            BitmapSizeOptions.FromEmptyOptions());

        bitmap.Dispose();
        graphics.Dispose();

        return imageSource;
    }
}

使用说明

使用 ToImageSource() 扩展方法将 System.Drawing.Icon 转换为 System.Media.ImageSource:

Icon icon = ...; // 获取你的图标
ImageSource imageSource = icon.ToImageSource();

注意:

确保拥有使用图标所需的权限。如果图标来自非托管 DLL,则可能需要调整应用程序的权限设置。

常见问题解答

1. 为什么需要将 Icon 转换为 ImageSource?

  • 在 WPF 应用程序中使用图标时,需要将其转换为 ImageSource。

2. 是否有其他方法可以将 Icon 转换为 ImageSource?

  • 除了上述方法外,还可以使用第三方库或直接从图像文件中创建 ImageSource。

3. 在哪里可以找到有关 Icon 和 ImageSource 的更多信息?

  • 有关 Icon 的更多信息,请参阅 MSDN 文档。
  • 有关 ImageSource 的更多信息,请参阅 WPF 文档。

4. 为什么我的应用程序无法使用转换后的 ImageSource?

  • 检查应用程序是否具有使用图标所需的权限。
  • 确保以正确的格式保存图像文件。

5. 如何在 UWP 应用程序中使用 ImageSource?

  • 在 UWP 应用程序中使用 ImageSource 与在 WPF 应用程序中类似。可以使用 XAML 或代码将其添加到 UI。