C# 将 System.Drawing.Icon 转换为 System.Media.ImageSource
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1127647/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert System.Drawing.Icon to System.Media.ImageSource
提问by Kevin Montrose
I've got an IntPtr marshaled across an unmanaged/managed boundary that corresponds to an Icon Handle. Converting it to an Icon is trivial via the FromHandle() method, and this was satisfactory until recently.
我有一个 IntPtr 在对应于图标句柄的非托管/托管边界上封送。通过 FromHandle() 方法将其转换为 Icon 是微不足道的,直到最近这还是令人满意的。
Basically, I've got enough thread weirdness going on now that the MTA/STA dance I've been playing to keep a hosted WinForm from breaking the primary (WPF-tastic) UI of the application is too brittle to stick with. So the WinForm has got to go.
基本上,由于我一直在玩的 MTA/STA 舞蹈使托管的 WinForm 不破坏应用程序的主要(WPF 风格)UI 太脆弱而无法坚持,因此基本上,我已经有了足够多的线程怪异现象。所以必须使用 WinForm。
So, how can I get an ImageSource version of an Icon?
那么,我怎样才能获得一个 ImageSource 版本的图标呢?
Note, I've tried ImageSourceConverter to no avail.
请注意,我试过 ImageSourceConverter 无济于事。
As an aside, I can get the underlying resource for somebut not all of the icons involved and they generally exist outside of my application's assembly (in fact, they often exist in unmanaged dll's).
顺便说一句,我可以获得一些但不是所有涉及的图标的底层资源,它们通常存在于我的应用程序程序集之外(实际上,它们通常存在于非托管 dll 中)。
采纳答案by Kenan E. K.
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();
回答by Darren
MemoryStream iconStream = new MemoryStream();
myForm.Icon.Save(iconStream);
iconStream.Seek(0, SeekOrigin.Begin);
_wpfForm.Icon = System.Windows.Media.Imaging.BitmapFrame.Create(iconStream);
回答by Derek Bartram
When using disposable streams it is almost always recommended to use 'using' blocks to force correct releasing 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 System.Drawing.Icon, and this.TargetWindow
is the target System.Windows.Window.
icon
源 System.Drawing.Icon在哪里,this.TargetWindow
目标 System.Windows.Window在哪里
。
回答by Byte
Simple conversion method without creating any extra objects:
无需创建任何额外对象的简单转换方法:
public static ImageSource ToImageSource(this Icon icon)
{
ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon(
icon.Handle,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
return imageSource;
}
回答by user3442716
There is a really simple solution to this problem.
这个问题有一个非常简单的解决方案。
Steps:
脚步:
(1) add image to resources in solution explorer -> resources.resx (2) edit image properties inside "Resources" directory in solution explorer and change "Build action" to "Resource"
(1) 将图像添加到解决方案资源管理器中的资源 -> resources.resx (2) 编辑解决方案资源管理器中“资源”目录中的图像属性并将“构建操作”更改为“资源”
In xaml, add the following...
在 xaml 中,添加以下内容...
Icon="resources/name of image" (where "name of image" is the name of the image you added to resources - see point (1).
Icon="resources/name of image"(其中“图像名称”是您添加到资源中的图像的名称 - 请参阅第 (1) 点)。
回答by TarmoPikaro
Somehow similar example, only tuned from developer's use cases...
不知何故类似的例子,只从开发人员的用例调整......
[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
回答by Justin Davis
Taking from some above this has created the highest quality of icons for my self. Loading the icons from a byte array. I use cache onload because if you don't you will get a disposed exception when you dispose the memory stream.
从上面的一些内容来看,这为我自己创造了最高质量的图标。从字节数组加载图标。我使用缓存 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);
}
}