Get icon 128*128 File type C#

情到浓时终转凉″ 提交于 2020-01-23 04:03:42

问题


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

Icon ico = Icon.ExtractAssociatedIcon(@"d:\\1.txt");
pictureBox1.Image = ico.ToBitmap();

and save the image from the pictureBox1, but that size is 32*32.

I really want a size 128*128.

How can I do that?


回答1:


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

Native wrapper

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
    );
}

Native structures

[Flags]
enum SHGFI : uint
{
    /// <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)]
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);
};


来源:https://stackoverflow.com/questions/28525925/get-icon-128128-file-type-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!