[英]Convert System.Drawing.Icon to System.Media.ImageSource
我在與圖標手柄相對應的不受管/受管邊界上整理了一個IntPtr。 通過FromHandle()方法將其轉換為Icon很簡單,直到最近它還是令人滿意的。
基本上,由於我一直在播放MTA / STA舞蹈以防止宿主的WinForm破壞應用程序的主(WPF原始)UI太脆弱,因此我一直在進行足夠的線程怪異操作。 因此WinForm必須開始。
那么,如何獲得Icon的ImageSource版本?
注意,我嘗試了ImageSourceConverter無濟於事。
順便說一句,我可以獲得某些但不是全部圖標的基礎資源,它們通常存在於應用程序的程序集之外(實際上,它們通常存在於非托管dll中)。
簡單的轉換方法,無需創建任何額外的對象:
public static ImageSource ToImageSource(this Icon icon)
{
ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon(
icon.Handle,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
return imageSource;
}
嘗試這個:
Icon img;
Bitmap bitmap = img.ToBitmap();
IntPtr hBitmap = bitmap.GetHbitmap();
ImageSource wpfBitmap =
Imaging.CreateBitmapSourceFromHBitmap(
hBitmap, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
更新 :納入亞歷克斯的建議,並將其作為擴展方法:
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();
使用一次性流時,幾乎總是建議使用“使用”塊來強制正確釋放資源。
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。
MemoryStream iconStream = new MemoryStream();
myForm.Icon.Save(iconStream);
iconStream.Seek(0, SeekOrigin.Begin);
_wpfForm.Icon = System.Windows.Media.Imaging.BitmapFrame.Create(iconStream);
從上面的觀點來看,這為我自己創造了最高質量的圖標。 從字節數組加載圖標。 我使用緩存加載,因為如果不這樣做,則在處理內存流時會得到處理后的異常。
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);
}
}
某種程度上類似的示例,僅根據開發人員的用例進行了調整...
[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
這個問題有一個非常簡單的解決方案。
腳步:
(1)將圖像添加到解決方案資源管理器中的資源-> resources.resx(2)在解決方案資源管理器中的“資源”目錄中編輯圖像屬性,並將“構建操作”更改為“資源”
在xaml中,添加以下內容...
Icon =“資源/圖像名稱”(其中“圖像名稱”是您添加到資源中的圖像名稱-請參見第(1)點)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.