source

시스템 변환그림그리기.아이콘에서 시스템으로Media.ImageSource

gigabyte 2023. 4. 24. 23:25
반응형

시스템 변환그림그리기.아이콘에서 시스템으로Media.ImageSource

아이콘 핸들에 대응하는 관리되지 않는 경계/관리되지 않는 경계에 걸쳐 IntPtr을 마셜링했습니다.FromHandle() 메서드로 아이콘으로 변환하는 것은 간단하며 최근까지 만족스러웠습니다.

기본적으로, 호스팅된 WinForm이 애플리케이션의 기본(WPF-tastic) UI를 깨는 것을 막기 위해 연주한 MTA/STA 춤은 너무 불안정하기 때문에 더 이상 사용할 수 없습니다.그래서 WinForm은 없어져야 합니다.

그러면 Icon의 ImageSource 버전을 입수하려면 어떻게 해야 하나요?

Image Source Converter를 사용해 봤지만 소용이 없었습니다.

이와는 별도로 관련된 아이콘의 일부에 대한 기본 리소스를 얻을 수 있습니다. 아이콘은 일반적으로 응용 프로그램의 어셈블리 외부에 존재합니다(실제로 관리되지 않는 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());

업데이트: 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();

일회용 스트림을 사용할 때는 거의 항상 '사용' 블록을 사용하여 리소스를 올바르게 해제하는 것이 좋습니다.

using (MemoryStream iconStream = new MemoryStream())
{
   icon.Save(iconStream);
   iconStream.Seek(0, SeekOrigin.Begin);

   this.TargetWindow.Icon = System.Windows.Media.Imaging.BitmapFrame.Create(iconStream);
}

어디에icon소스 시스템입니다.그림그리기.아이콘 및this.TargetWindow대상 시스템입니다.창문들.창문이요.

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) Solution Explorer -> Resources.resx (2)의 리소스에 이미지를 추가하고 솔루션 탐색기의 "Resources" 디렉토리 내의 이미지 속성을 편집하여 "Build action"을 "Resource"로 변경합니다.

xaml에 다음 추가...

아이콘="리소스/이미지 이름" (여기서 "이미지 이름"은 리소스에 추가한 이미지의 이름입니다.) 지점 (1)을 참조하십시오.

언급URL : https://stackoverflow.com/questions/1127647/convert-system-drawing-icon-to-system-media-imagesource

반응형