I need to get the icon of a file type doc or txt
It\'s size should be 128*128 and be saved as an png or ico file in good quality.
I used
Ic
There is no icon-size 128x128 available from the Shell API SHGetImageList. The sizes range from the Win95 era of 16x16 and 32x32 via XP's 48x48 and finally Vista that added the 256x256 size.
To get a png file from any of the available icon sizes I followed the blog How do I get a high resolution icon for a file from Raymond Chen. I ported his code to c# where I borrowed pieces from this answer.
To follow Raymond's article here are the main two functions you need:
int GetIconIndex(string pszFile)
{
SHFILEINFO sfi = new SHFILEINFO();
Shell32.SHGetFileInfo(pszFile
, 0
, ref sfi
, (uint)System.Runtime.InteropServices.Marshal.SizeOf(sfi)
, (uint) (SHGFI.SysIconIndex | SHGFI.LargeIcon | SHGFI.UseFileAttributes));
return sfi.iIcon;
}
// 256*256
IntPtr GetJumboIcon(int iImage)
{
IImageList spiml = null;
Guid guil = new Guid(IID_IImageList2);//or IID_IImageList
Shell32.SHGetImageList(Shell32.SHIL_JUMBO, ref guil, ref spiml);
IntPtr hIcon = IntPtr.Zero;
spiml.GetIcon(iImage, Shell32.ILD_TRANSPARENT | Shell32.ILD_IMAGE, ref hIcon); //
return hIcon;
}
The method GetIconIndex calls into the native SHGetFileIfo to get the icon index for the file (or extension) you provided in the name parameter.
To get the actual icon the method GetJumboIcon
calls the native SHGetImageList with a size attribute.
To let it all work you combine the calls like so:
IntPtr hIcon = GetJumboIcon(GetIconIndex("*.txt"));
// from native to managed
using (Icon ico = (Icon)System.Drawing.Icon.FromHandle(hIcon).Clone())
{
// save to file (or show in a picture box)
ico.ToBitmap().Save("txticon.png", ImageFormat.Png);
}
Shell32.DestroyIcon(hIcon); // don't forget to cleanup
To get an 48x48 icon you can extend the code with this method:
// 48X48
IntPtr GetXLIcon(int iImage)
{
IImageList spiml = null;
Guid guil = new Guid(IID_IImageList);//or IID_IImageList
Shell32.SHGetImageList(Shell32.SHIL_EXTRALARGE, ref guil, ref spiml);
IntPtr hIcon = IntPtr.Zero;
spiml.GetIcon(iImage, Shell32.ILD_TRANSPARENT | Shell32.ILD_IMAGE, ref hIcon); //
return hIcon;
}
Due to interaction with unmanaged code you need to compile the project with the /unsafe option enabled. You can set that from visual studio by changing the project properties, goto to the Build tab and put a checkmark for the Allow unsafe code option. See this question why that is needed and here is the official MSDN documentation
To call the native win32 api the functions and structures are wrapped in a static class that you need to include as well in your project. Most of those wrappers and the structures can be found at Pinvoke.net
const string IID_IImageList = "46EB5926-582E-4017-9FDF-E8998DAA0950";
const string IID_IImageList2 = "192B9D83-50FC-457B-90A0-2B82A8B5DAE1";
public static class Shell32
{
public const int SHIL_LARGE =0x0;
public const int SHIL_SMALL =0x1;
public const int SHIL_EXTRALARGE =0x2;
public const int SHIL_SYSSMALL =0x3;
public const int SHIL_JUMBO = 0x4;
public const int SHIL_LAST = 0x4;
public const int ILD_TRANSPARENT = 0x00000001;
public const int ILD_IMAGE = 0x00000020;
[DllImport("shell32.dll", EntryPoint = "#727")]
public extern static int SHGetImageList(int iImageList, ref Guid riid, ref IImageList ppv);
[DllImport("user32.dll", EntryPoint = "DestroyIcon", SetLastError = true)]
public static unsafe extern int DestroyIcon(IntPtr hIcon);
[DllImport("shell32.dll")]
public static extern uint SHGetIDListFromObject([MarshalAs(UnmanagedType.IUnknown)] object iUnknown, out IntPtr ppidl);
[DllImport("Shell32.dll")]
public static extern IntPtr SHGetFileInfo(
string pszPath,
uint dwFileAttributes,
ref SHFILEINFO psfi,
uint cbFileInfo,
uint uFlags
);
}
[Flags]
enum SHGFI : uint
{
/// get icon
Icon = 0x000000100,
/// get display name
DisplayName = 0x000000200,
/// get type name
TypeName = 0x000000400,
/// get attributes
Attributes = 0x000000800,
/// get icon location
IconLocation = 0x000001000,
/// return exe type
ExeType = 0x000002000,
/// get system icon index
SysIconIndex = 0x000004000,
/// put a link overlay on icon
LinkOverlay = 0x000008000,
/// show icon in selected state
Selected = 0x000010000,
/// get only specified attributes
Attr_Specified = 0x000020000,
/// get large icon
LargeIcon = 0x000000000,
/// get small icon
SmallIcon = 0x000000001,
/// get open icon
OpenIcon = 0x000000002,
/// get shell size icon
ShellIconSize = 0x000000004,
/// pszPath is a pidl
PIDL = 0x000000008,
/// use passed dwFileAttribute
UseFileAttributes = 0x000000010,
/// apply the appropriate overlays
AddOverlays = 0x000000020,
/// Get the index of the overlay in the upper 8 bits of the iIcon
OverlayIndex = 0x000000040,
}
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
public const int NAMESIZE = 80;
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left, top, right, bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
int x;
int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGELISTDRAWPARAMS
{
public int cbSize;
public IntPtr himl;
public int i;
public IntPtr hdcDst;
public int x;
public int y;
public int cx;
public int cy;
public int xBitmap; // x offest from the upperleft of bitmap
public int yBitmap; // y offset from the upperleft of bitmap
public int rgbBk;
public int rgbFg;
public int fStyle;
public int dwRop;
public int fState;
public int Frame;
public int crEffect;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGEINFO
{
public IntPtr hbmImage;
public IntPtr hbmMask;
public int Unused1;
public int Unused2;
public RECT rcImage;
}
[ComImportAttribute()]
[GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IImageList
{
[PreserveSig]
int Add(
IntPtr hbmImage,
IntPtr hbmMask,
ref int pi);
[PreserveSig]
int ReplaceIcon(
int i,
IntPtr hicon,
ref int pi);
[PreserveSig]
int SetOverlayImage(
int iImage,
int iOverlay);
[PreserveSig]
int Replace(
int i,
IntPtr hbmImage,
IntPtr hbmMask);
[PreserveSig]
int AddMasked(
IntPtr hbmImage,
int crMask,
ref int pi);
[PreserveSig]
int Draw(
ref IMAGELISTDRAWPARAMS pimldp);
[PreserveSig]
int Remove(
int i);
[PreserveSig]
int GetIcon(
int i,
int flags,
ref IntPtr picon);
[PreserveSig]
int GetImageInfo(
int i,
ref IMAGEINFO pImageInfo);
[PreserveSig]
int Copy(
int iDst,
IImageList punkSrc,
int iSrc,
int uFlags);
[PreserveSig]
int Merge(
int i1,
IImageList punk2,
int i2,
int dx,
int dy,
ref Guid riid,
ref IntPtr ppv);
[PreserveSig]
int Clone(
ref Guid riid,
ref IntPtr ppv);
[PreserveSig]
int GetImageRect(
int i,
ref RECT prc);
[PreserveSig]
int GetIconSize(
ref int cx,
ref int cy);
[PreserveSig]
int SetIconSize(
int cx,
int cy);
[PreserveSig]
int GetImageCount(
ref int pi);
[PreserveSig]
int SetImageCount(
int uNewCount);
[PreserveSig]
int SetBkColor(
int clrBk,
ref int pclr);
[PreserveSig]
int GetBkColor(
ref int pclr);
[PreserveSig]
int BeginDrag(
int iTrack,
int dxHotspot,
int dyHotspot);
[PreserveSig]
int EndDrag();
[PreserveSig]
int DragEnter(
IntPtr hwndLock,
int x,
int y);
[PreserveSig]
int DragLeave(
IntPtr hwndLock);
[PreserveSig]
int DragMove(
int x,
int y);
[PreserveSig]
int SetDragCursorImage(
ref IImageList punk,
int iDrag,
int dxHotspot,
int dyHotspot);
[PreserveSig]
int DragShowNolock(
int fShow);
[PreserveSig]
int GetDragImage(
ref POINT ppt,
ref POINT pptHotspot,
ref Guid riid,
ref IntPtr ppv);
[PreserveSig]
int GetItemFlags(
int i,
ref int dwFlags);
[PreserveSig]
int GetOverlayImage(
int iOverlay,
ref int piIndex);
};