簡體   English   中英

將System.Drawing.Icon轉換為System.Media.ImageSource

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM