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

时间:2009-07-14 20:03:52

标签: c# wpf windows winforms

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

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

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

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

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

7 个答案:

答案 0 :(得分:80)

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

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

        return imageSource;
    }

答案 1 :(得分:51)

试试这个:

Icon img;

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

ImageSource wpfBitmap =
     Imaging.CreateBitmapSourceFromHBitmap(
          hBitmap, IntPtr.Zero, Int32Rect.Empty, 
          BitmapSizeOptions.FromEmptyOptions());

更新:纳入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;
    }
}

然后你可以这样做:

ImageSource wpfBitmap = img.ToImageSource();

答案 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);
}

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

答案 3 :(得分:9)

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

答案 4 :(得分:1)

从上面的一些方面来看,这为我自己创造了最高质量的图标。从字节数组加载图标。我使用缓存onload,因为如果你不这样做,你将在处理内存流时得到一个处理异常。

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

答案 5 :(得分:0)

以某种方式类似的例子,仅从开发人员的用例...

调整
    JavaReceiverInputDStream<String> streamData1 = ssc.socketTextStream("localhost",996,
            StorageLevels.MEMORY_AND_DISK_SER);

    JavaReceiverInputDStream<String> streamData2 = ssc.socketTextStream("localhost", 9995,StorageLevels.MEMORY_AND_DISK_SER);

    JavaPairDStream<Integer, String> dataStream1= streamData1.mapToPair(new PairFunction<String, Integer, String>() {
        public Tuple2<Integer, String> call(String stream) throws Exception {


            Tuple2<Integer,String> streamPair= new Tuple2<Integer, String>(1, stream);

            return streamPair;
        }
    });

    JavaPairDStream<Integer, String> dataStream2= streamData2.mapToPair(new PairFunction<String, Integer, String>() {
        public Tuple2<Integer, String> call(String stream) throws Exception {


            Tuple2<Integer,String> streamPair= new Tuple2<Integer, String>(2, stream);

            return streamPair;
        }
    });

dataStream2.print(); //for example

答案 6 :(得分:-2)

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

步骤:

(1)将图像添加到解决方案资源管理器中的资源 - &gt; resources.resx (2)编辑里面的图像属性&#34;资源&#34;解决方案资源管理器中的目录并更改&#34;构建操作&#34;到&#34;资源&#34;

在xaml中,添加以下内容......

Icon =&#34;资源/图片名称&#34; (其中&#34;图像名称&#34;是您添加到资源的图像的名称 - 请参阅第(1)点。