C#获取文件超大图标256*256(转)
在开发工程中,我们经常会需要获取文件的图标,以便在自定义的程序中进行显示。通常情况下,我们可以通过Shell32
库中的SHGetFileInfo
函数实现。但是在Windows Vista及以上操作系统中,系统引入了超大图标(256*256)的支持,而SHGetFileInfo
无法获取超大图标。本文将介绍如何使用C#获取文件的超大图标。
Windows API
在了解获取超大图标之前,我们需要先了解几个Windows API。这些API用于Windows Shell操作,以及获取资源的相关信息。
SHGetStockIconInfo
函数
这个函数用于获取Windows Stock Icon(Windows自带的一些标准图标),其中参数_In_
传入的SHSTOCKICONID
枚举值确定我们要获取哪个Stock Icon。另外,参数_Out_
传出的结构体SHSTOCKICONINFO
包含了获取到的图标的信息。
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHSTOCKICONINFO
{
public UInt32 cbSize;
public IntPtr hIcon;
public int iSysImageIndex;
public int iIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szPath;
public SHSTOCKICONINFO(UInt32 size) : this()
{
cbSize = size;
}
}
public enum SHSTOCKICONID : uint
{
SIID_DOCNOASSOC = 0,
SIID_DOCASSOC = 1,
SIID_APPLICATION = 2,
SIID_FOLDER = 3,
SIID_FOLDEROPEN = 4,
SIID_DRIVE525 = 5,
SIID_DRIVE35 = 6,
SIID_DRIVEREMOVE = 7,
SIID_DRIVEFIXED = 8,
SIID_DRIVENET = 9,
SIID_DRIVENETDISABLED = 10,
SIID_DRIVECD = 11,
SIID_DRIVERAM = 12,
SIID_WORLD = 13,
SIID_SERVER = 15,
SIID_PRINTER = 16,
SIID_MYNETWORK = 17,
SIID_FIND = 22,
SIID_HELP = 23,
SIID_SHARE = 28,
SIID_LINK = 29,
SIID_SLOWFILE = 30,
SIID_RECYCLER = 31,
SIID_RECYCLERFULL = 32,
SIID_MEDIACDAUDIO = 40,
SIID_LOCK = 47,
SIID_AUTOLIST = 49,
SIID_PRINTERNET = 50,
SIID_SERVERSHARE = 51,
SIID_PRINTERFAX = 52,
SIID_PRINTERFAXNET = 53,
SIID_PRINTERFILE = 54,
SIID_STACK = 55,
SIID_MEDIASVCD = 56,
SIID_STUFFEDFOLDER = 57,
SIID_DRIVEUNKNOWN = 58,
SIID_DRIVEDVD = 59,
SIID_MEDIADVD = 60,
SIID_MEDIADVDRAM = 61,
SIID_MEDIADVDRW = 62,
SIID_MEDIADVDR = 63,
SIID_MEDIADVDROM = 64,
SIID_MEDIACDAUDIOPLUS = 65,
SIID_MEDIACDRW = 66,
SIID_MEDIACDR = 67,
SIID_MEDIACDBURN = 68,
SIID_MEDIABLANKCD = 69,
SIID_MEDIACDROM = 70,
SIID_AUDIOFILES = 71,
SIID_IMAGEFILES = 72,
SIID_VIDEOFILES = 73,
SIID_MIXEDFILES = 74,
SIID_FOLDERBACK = 75,
SIID_FOLDERFRONT = 76,
SIID_SHIELD = 77,
SIID_WARNING = 78,
SIID_INFO = 79,
SIID_ERROR = 80,
SIID_KEY = 81,
SIID_SOFTWARE = 82,
SIID_RENAME = 83,
SIID_DELETE = 84,
SIID_MEDIAAUDIODVD = 85,
SIID_MEDIAMOVIEDVD = 86,
SIID_MEDIAENHANCEDCD = 87,
SIID_MEDIAENHANCEDDVD = 88,
SIID_MEDIAHDDVD = 89,
SIID_MEDIABLURAY = 90,
SIID_MEDIAVCD = 91,
SIID_MEDIADVDPLUSR = 92,
SIID_MEDIADVDPLUSRW = 93,
SIID_DESKTOPPC = 94,
SIID_MOBILEPC = 95,
SIID_USERS = 96,
SIID_MEDIANET = 97,
SIID_UAVIDEO = 98,
SIID_UATV = 99,
SIID_MEDIAVIDEOCD = 100,
SIID_MEDIAVIDEODVD = 101,
SIID_MEDIATVCOMPUTER = 102,
SIID_MEDIATV = 103,
SIID_MEDIAAUDIOCD = 104,
SIID_MEDIAAUDIOBOOK = 105,
SIID_MEDIAMUSIC = 106,
SIID_DEVICECELLPHONE = 107,
SIID_DEVICECAMERA = 108,
SIID_DEVICEVIDEOCAMERA = 109,
SIID_DEVICEAUDIOPLAYER = 110,
SIID_NETWORKCONNECT = 112,
SIID_INTERNET = 113,
SIID_ZIPFILE = 114,
SIID_SETTINGS = 117,
SIID_DRIVEHDDVD = 118,
SIID_DRIVEBD = 119,
SIID_MEDIAHDDVDROM = 120,
SIID_MEDIAHDDVDR = 121,
SIID_MEDIAHDDVDRAM = 122,
SIID_MEDIABDROM = 123,
SIID_MEDIABDR = 124,
SIID_MEDIABDRE = 125,
SIID_CLUSTEREDDRIVE = 126,
SIID_MAX_ICONS = 175
}
[DllImport("Shell32.dll", SetLastError = true)]
public static extern int SHGetStockIconInfo(SHSTOCKICONID siid, uint uFlags, ref SHSTOCKICONINFO psii);
SHCreateItemFromParsingName
函数
这个函数用于根据文件路径创建IShellItem
实例。我们可以通过该接口获取文件的超大图标。
[ComImportAttribute()]
[GuidAttribute("43826D1E-E718-42EE-BC55-A1E261C37BFE")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellItem
{
void BindToHandler(IntPtr pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid bhid, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv);
void GetParent(out IShellItem ppsi);
void GetDisplayName(uint sigdnName, out IntPtr ppszName);
void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
void Compare(IShellItem psi, uint hint, out int piOrder);
}
[DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
public static extern void SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string file, IntPtr pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppv);
获取超大图标
获取文件的超大图标需要用到IShellItemImageFactory
接口,该接口提供了获取Item Image的方法。
我们首先需要通过文件路径创建IShellItem
实例,然后利用IShellItemImageFactory
获取超大图标。
public static BitmapSource GetLargeIcon(string fileName)
{
SHCreateItemFromParsingName(fileName, IntPtr.Zero, typeof(IShellItem).GUID, out IShellItem nativeShellItem);
IntPtr shellItemPtr = Marshal.GetComInterfaceForObject(nativeShellItem, typeof(IShellItem));
IntPtr shellItemImageFactoryPtr = IntPtr.Zero;
Guid shellItemImageFactoryGuid = new Guid("bcc18b79-ba16-442f-80c4-8a59c30c463b");
try
{
Marshal.QueryInterface(shellItemPtr, ref shellItemImageFactoryGuid, out shellItemImageFactoryPtr);
IShellItemImageFactory shellItemImageFactory = (IShellItemImageFactory)Marshal.GetObjectForIUnknown(shellItemImageFactoryPtr);
uint iconSize = 256;
System.Runtime.InteropServices.ComTypes.FILETIME ft = new System.Runtime.InteropServices.ComTypes.FILETIME();
IntPtr hBitmap = IntPtr.Zero;
shellItemImageFactory.GetImage(new SIZE()
{
cx = (int)iconSize,
cy = (int)iconSize
}, 0x0, ref ft, out hBitmap);
if (hBitmap != IntPtr.Zero)
{
return Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight((int)iconSize, (int)iconSize));
}
return null;
}
finally
{
Marshal.ReleaseComObject(nativeShellItem);
if (shellItemImageFactoryPtr != IntPtr.Zero)
{
Marshal.Release(shellItemImageFactoryPtr);
}
}
}
结语
通过以上实现,我们可以在Windows Vista及以上操作系统中获取文件的超大图标。同时,我们也了解到了相关的Windows API,并可以借鉴其中的方法来实现其他功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c#获取文件超大图标256*256(转) - Python技术站