2009-08-25 27 views
20

Hiện tại tôi đang nhận được biểu tượng gốc bằng cách gọi SHGetFileInfo. Sau đó, tôi chuyển đổi nó thành một bitmap bằng cách sử dụng đoạn mã sau. Bitmap cuối cùng được hiển thị trong biểu mẫu WPF.Làm cách nào để hiển thị biểu tượng tệp Windows trong WPF?

Có cách nào nhanh hơn để làm điều tương tự không?

try 
     { 
      using (Icon i = Icon.FromHandle(shinfo.hIcon)) 
      { 
       Bitmap bmp = i.ToBitmap(); 
       MemoryStream strm = new MemoryStream(); 
       bmp.Save(strm, System.Drawing.Imaging.ImageFormat.Png); 
       BitmapImage bmpImage = new BitmapImage(); 
       bmpImage.BeginInit(); 
       strm.Seek(0, SeekOrigin.Begin); 
       bmpImage.StreamSource = strm; 
       bmpImage.EndInit(); 

       return bmpImage; 
      } 
     } 
     finally 
     { 
      Win32.DestroyIcon(hImgLarge); 
     } 

Trả lời

19
using System.Windows.Interop; 

... 

using (Icon i = Icon.FromHandle(shinfo.hIcon)) 
{ 

    ImageSource img = Imaging.CreateBitmapSourceFromHIcon(
          i.Handle, 
          new Int32Rect(0,0,i.Width, i.Height), 
          BitmapSizeOptions.FromEmptyOptions()); 
} 
1

I belive có đơn giản hơn (thêm quản lý) cách giải quyết này hilighted đây. http://www.pchenry.com/Home/tabid/36/EntryID/193/Default.aspx

Điểm mấu chốt của giải pháp là ở đây.

System.Drawing.Icon formIcon = IconsInWPF.Properties.Resources.Habs; 
MemoryStream stream = new MemoryStream(); 
formIcon.Save(stream); 
this.Icon = BitmapFrame.Create(stream); 
+2

Hãy nhớ để xử lý các nguồn lực của bạn sau khi sử dụng chúng. Trong trường hợp này, luồng của bạn không bị đóng. –

5

Mã của Thomas có thể được đơn giản hóa hơn nữa. Dưới đây là đoạn code đầy đủ với kiểm tra lỗi thêm:

  Interop.SHGetFileInfo(path, isFile, ref pifFileInfo); 
      IntPtr iconHandle = pifFileInfo.hIcon; 
      if (IntPtr.Zero == iconHandle) 
       return DefaultImgSrc; 
      ImageSource img = Imaging.CreateBitmapSourceFromHIcon(
         iconHandle, 
         Int32Rect.Empty, 
         BitmapSizeOptions.FromEmptyOptions()); 
      User32.DestroyIcon(iconHandle); 
      return img; 

Sự khác biệt là:

  • không cần phải tạo đối tượng Biểu tượng
  • hãy chắc chắn để xử lý một trường hợp iconHandle là 0 (IntPtr.Zero) bằng ví dụ trở về một số đối tượng được xác định trước ImageSource
  • hãy chắc chắn để sử dụng win32 api DestroyIcon() nếu nó xuất phát từ SHGetFileInfo()
+0

Bạn cũng có thể cung cấp mã Interop không? Tôi gặp sự cố khi khớp mã của bạn với chữ ký hàm của SHGetFileInfo từ API Windows. Tất cả các giải pháp khác tôi đã tìm thấy sử dụng System.Drawing, có vẻ như 100% không tương thích với WPF, vậy tại sao lại sử dụng nó. Điều này có vẻ thẳng nhất. Nếu tôi có thể làm cho nó hoạt động. – ygoe

+0

Lớp Interop & kết hợp khác trong [câu trả lời của tôi] (http://stackoverflow.com/questions/1325625/how-do-i-display-a-windows-file-icon-in-wpf#answer-29819585) bên dưới (quá dài để nhận xét) –

23

Làm thế nào về một cái gì đó như:

var icon = System.Drawing.Icon.ExtractAssociatedIcon(fileName); 
var bmp = icon.ToBitmap() 
+0

Rõ ràng là bạn không đủ phức tạp;) – ocodo

+6

@Slomojo using System.Drawing và Bitmap map = Icon.ExtractAssociatedIcon (tên tệp) .ToBitmap() cũng hoạt động ... – msfanboy

+0

ToBitmap() mất alpha kênh – Prat

8

Kết hợp Krzysztof Kowalczyk answer với một số googling, i tạo thành này:

Phương pháp:

/* 
using System; 
using System.Runtime.InteropServices; 
using System.Windows; 
using System.Windows.Interop; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
*/ 

    public static ImageSource GetIcon(string strPath, bool bSmall) 
     { 
      Interop.SHFILEINFO info = new Interop.SHFILEINFO(true); 
      int cbFileInfo = Marshal.SizeOf(info); 
      Interop.SHGFI flags; 
      if (bSmall) 
      flags = Interop.SHGFI.Icon | Interop.SHGFI.SmallIcon | Interop.SHGFI.UseFileAttributes; 
      else 
      flags = Interop.SHGFI.Icon | Interop.SHGFI.LargeIcon | Interop.SHGFI.UseFileAttributes; 

      Interop.SHGetFileInfo(strPath, 256, out info, (uint)cbFileInfo, flags); 

      IntPtr iconHandle = info.hIcon; 
      //if (IntPtr.Zero == iconHandle) // not needed, always return icon (blank) 
      // return DefaultImgSrc; 
      ImageSource img = Imaging.CreateBitmapSourceFromHIcon(
         iconHandle, 
         Int32Rect.Empty, 
         BitmapSizeOptions.FromEmptyOptions()); 
      Interop.DestroyIcon(iconHandle); 
      return img; 
     } 

và Interop lớp:

using System; 
using System.Runtime.InteropServices; 
public static class Interop 
    { 
    /// <summary>Maximal Length of unmanaged Windows-Path-strings</summary> 
    private const int MAX_PATH = 260; 
    /// <summary>Maximal Length of unmanaged Typename</summary> 
    private const int MAX_TYPE = 80; 


    [Flags] 
    public enum SHGFI : int 
    { 
     /// <summary>get icon</summary> 
     Icon = 0x000000100, 
     /// <summary>get display name</summary> 
     DisplayName = 0x000000200, 
     /// <summary>get type name</summary> 
     TypeName = 0x000000400, 
     /// <summary>get attributes</summary> 
     Attributes = 0x000000800, 
     /// <summary>get icon location</summary> 
     IconLocation = 0x000001000, 
     /// <summary>return exe type</summary> 
     ExeType = 0x000002000, 
     /// <summary>get system icon index</summary> 
     SysIconIndex = 0x000004000, 
     /// <summary>put a link overlay on icon</summary> 
     LinkOverlay = 0x000008000, 
     /// <summary>show icon in selected state</summary> 
     Selected = 0x000010000, 
     /// <summary>get only specified attributes</summary> 
     Attr_Specified = 0x000020000, 
     /// <summary>get large icon</summary> 
     LargeIcon = 0x000000000, 
     /// <summary>get small icon</summary> 
     SmallIcon = 0x000000001, 
     /// <summary>get open icon</summary> 
     OpenIcon = 0x000000002, 
     /// <summary>get shell size icon</summary> 
     ShellIconSize = 0x000000004, 
     /// <summary>pszPath is a pidl</summary> 
     PIDL = 0x000000008, 
     /// <summary>use passed dwFileAttribute</summary> 
     UseFileAttributes = 0x000000010, 
     /// <summary>apply the appropriate overlays</summary> 
     AddOverlays = 0x000000020, 
     /// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary> 
     OverlayIndex = 0x000000040, 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct SHFILEINFO 
    { 
     public SHFILEINFO(bool b) 
     { 
     hIcon = IntPtr.Zero; 
     iIcon = 0; 
     dwAttributes = 0; 
     szDisplayName = ""; 
     szTypeName = ""; 
     } 
     public IntPtr hIcon; 
     public int iIcon; 
     public uint dwAttributes; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] 
     public string szDisplayName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_TYPE)] 
     public string szTypeName; 
    }; 

    [DllImport("shell32.dll", CharSet = CharSet.Auto)] 
    public static extern int SHGetFileInfo(
     string pszPath, 
     int dwFileAttributes, 
     out SHFILEINFO psfi, 
     uint cbfileInfo, 
     SHGFI uFlags); 

    [DllImport("user32.dll", SetLastError = true)] 
    public static extern bool DestroyIcon(IntPtr hIcon); 
    } 

source

+1

Giải pháp Sao chép/Dán! ... +1. Chỉ cần một bình luận nhỏ mặc dù: Bạn nên gắn bó với "BitmapSource" cơ bản thay vì "ImageSource" như một lần thúc đẩy nó là khó hơn để quay trở lại lớp cơ sở. Câu trả lời hoàn hảo khác. Cảm ơn. – VeV

+0

Hoạt động hoàn hảo.Một cải tiến: Vì việc tải biểu tượng cho một số tệp có thể mất một chút thời gian, bạn có thể muốn thực hiện nó trong chuỗi công việc. Để có thể sử dụng một hình ảnh như vậy trong giao diện người dùng, nó phải được đóng băng: 'img.Freeze();' Nó sẽ không thay đổi. – ygoe

+0

Giải pháp tuyệt vời. Tôi mở rộng nó để cũng hỗ trợ các thư mục. Thay vì chuyển số ma thuật 256 đến SHGetFileInfo, tôi chuyển 'FILE_ATTRIBUTE_DIRECTORY' (0x10) khi tôi muốn truy xuất biểu tượng thư mục,' FILE_ATTRIBUTE_NORMAL' (0x80) nếu không. Tôi đã thêm hai giá trị này làm hằng số bên trong lớp Interop. Thông tin được sử dụng từ [đây] (https://stackoverflow.com/questions/1599235/how-do-i-fetch-the-folder-icon-on-windows-7-using-shell32-shgetfileinfo) và [tại đây] (https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117(v=vs.85).aspx). –

Các vấn đề liên quan