c# - studio - ¿Cómo muestro un icono de archivo de Windows en WPF?
visual studio icons (5)
¿Qué tal algo como:
var icon = System.Drawing.Icon.ExtractAssociatedIcon(fileName);
var bmp = icon.ToBitmap()
Actualmente estoy recibiendo un icono nativo llamando a SHGetFileInfo. Luego, lo estoy convirtiendo en un mapa de bits usando el siguiente código. El mapa de bits finalmente se muestra en el formulario WPF.
¿Hay una manera más rápida de hacer lo mismo?
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);
}
Combinando la respuesta de Krzysztof Kowalczyk con un poco de google, inventé esto:
Método:
/*
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;
}
y clase de interoperabilidad:
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);
}
Creo que hay una forma más simple (más administrada) de resolver esto aquí. http://www.pchenry.com/Home/tabid/36/EntryID/193/Default.aspx
El quid es de la solución está aquí.
System.Drawing.Icon formIcon = IconsInWPF.Properties.Resources.Habs;
MemoryStream stream = new MemoryStream();
formIcon.Save(stream);
this.Icon = BitmapFrame.Create(stream);
El código de Thomas podría simplificarse aún más. Aquí está el código completo con verificación de errores adicionales:
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;
La diferencia es:
- no es necesario crear un objeto Icon
- asegúrese de manejar un caso donde iconHandle es 0 (IntPtr.Zero), por ejemplo, devolviendo un objeto ImageSource predefinido
- asegúrese de usar win32 api DestroyIcon () si proviene de SHGetFileInfo ()
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());
}