这是在网上看到的一段代码 用来获得系统文件对应的图标 ,仅以获得小图标为列
#region DLLIMPORT
// Retrieves information about an object in the file system,
// such as a file, a folder, a directory, or a drive root.
[DllImport("shell32",
EntryPoint = "SHGetFileInfo",
ExactSpelling = false,
CharSet = CharSet.Auto,
SetLastError = true)]
private static extern IntPtr SHGetFileInfo(
string pszPath, //指定的文件名
FILE_ATTRIBUTE dwFileAttributes, //文件属性
ref SHFILEINFO sfi, //返回获得的文件信息,是一个记录类型
int cbFileInfo, //文件的类型名
SHGFI uFlags);
#endregion
#region STRUCTS
// Contains information about a file object
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct SHFILEINFO
{
public IntPtr hIcon; //文件的图标句柄
public IntPtr iIcon; //图标的系统索引号
public uint dwAttributes; //文件的属性值
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName; //文件的显示名
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName; //文件的类型名
};
#endregion
#region Enums
// Flags that specify the file information to retrieve with SHGetFileInfo
[Flags]
public enum SHGFI : uint
{
ADDOVERLAYS = 0x20,
ATTR_SPECIFIED = 0x20000,
ATTRIBUTES = 0x800, //获得属性
DISPLAYNAME = 0x200, //获得显示名
EXETYPE = 0x2000,
ICON = 0x100, //获得图标
ICONLOCATION = 0x1000,
LARGEICON = 0, //获得大图标
LINKOVERLAY = 0x8000,
OPENICON = 2,
OVERLAYINDEX = 0x40,
PIDL = 8,
SELECTED = 0x10000,
SHELLICONSIZE = 4,
SMALLICON = 1, //获得小图标
SYSICONINDEX = 0x4000,
TYPENAME = 0x400, //获得类型名
USEFILEATTRIBUTES = 0x10
}
// Flags that specify the file information to retrieve with SHGetFileInfo
[Flags]
public enum FILE_ATTRIBUTE
{
READONLY = 0x00000001,
HIDDEN = 0x00000002,
SYSTEM = 0x00000004,
DIRECTORY = 0x00000010,
ARCHIVE = 0x00000020,
DEVICE = 0x00000040,
NORMAL = 0x00000080,
TEMPORARY = 0x00000100,
SPARSE_FILE = 0x00000200,
REPARSE_POINT = 0x00000400,
COMPRESSED = 0x00000800,
OFFLINE = 0x00001000,
NOT_CONTENT_INDEXED = 0x00002000,
ENCRYPTED = 0x00004000
}
#endregion
#region Variables
//保存小图标列表
private static System.Windows.Forms.ImageList smallImageList;
private static List<string> FileExtList = new List<string>();
static SystemFileIcon()
{
smallImageList = new System.Windows.Forms.ImageList();
//将 ImageList中的图标设置为32位色图标,这样可以得到较好的显示效果
smallImageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
addForderIcon();
}
#endregion
#region PrivateMethods
/// <summary>
/// 获取系统图标
/// </summary>
/// <param name="path">文件名</param>
/// <param name="dwAttr">文件信息</param>
/// <param name="dwFlag">获取信息控制字</param>
/// <returns></returns>
private static Icon GetIcon(string path, FILE_ATTRIBUTE dwAttr, SHGFI dwFlag)
{
SHFILEINFO fi = new SHFILEINFO();
Icon ic = null;
int iTotal = (int)SHGetFileInfo(path, dwAttr, ref fi, 0, dwFlag);
ic = Icon.FromHandle(fi.hIcon);
return ic;
}
/// <summary>
/// 向smallInamgeList和largeImageList中
/// 加入相应文件对应的图标
/// </summary>
/// <param name="fileName"></param>
private static void addFileIcon(string fileName)
{
smallImageList.Images.Add(GetIcon(fileName,
FILE_ATTRIBUTE.NORMAL,
SHGFI.USEFILEATTRIBUTES | SHGFI.ICON | SHGFI.LARGEICON));
}
private static void addForderIcon()
{
smallImageList.Images.Add(GetIcon("dic",
FILE_ATTRIBUTE.DIRECTORY,
SHGFI.USEFILEATTRIBUTES | SHGFI.ICON | SHGFI.LARGEICON));
}
#endregion
#region PublicMethods
/// <summary>
/// 获取系统的小图标列表
/// </summary>
public static System.Windows.Forms.ImageList SmallImageList
{
get
{
return smallImageList;
}
}
/// <summary>
/// 文件对应的图标在ImageList中的索引号
/// (在SmallImageList,LargeImageList中的索引号是相同的)
/// </summary>
/// <param name="fileName">扩展名 如 .docx</param>
/// <returns>索引号</returns>
public static int ImageIndex(string fileName)
{
int index = 0;
int extIndex = fileName.LastIndexOf('.');
if (extIndex < 0)//没有扩展名的文件当作文件夹处理
{
extIndex = 2;
}
else//文件图标索引获取
{
addFileIcon(fileName);//装载图标到ImageList中
index = smallImageList.Images.Count - 1;
}
return index;
}
#endregion
}
分析上述代码发现 每次传递一个文件的时候都是获得该文件的图标,然后添加到集合中,返回集合最后一个index,即获得了该文件的图标!可是想一想,如果文件量很大呢?
10000个文件,这个ImageList得占多大的内存,由于这里有重复的文件格式,所以应该做如下处理!
思路是:用List<string> List记录已经添加到ImageList的文件类型,如果已经添加,直接返回该文件在List中的索引,如果没有添加,添加到ImageList和List中,返回ImageList
最后一个元素的索引
经验证后,确实不会报出内存不足!
/// <summary>
/// 文件对应的图标在ImageList中的索引号
/// (在SmallImageList,LargeImageList中的索引号是相同的)
/// </summary>
/// <param name="fileName">扩展名 如 .docx</param>
/// <returns>索引号</returns>
public static int ImageIndex(string fileName)
{
int index = 0;
int extIndex = fileName.LastIndexOf('.');
if (extIndex < 0)//没有扩展名的文件当作文件夹处理
{
extIndex = 2;
}
else//文件图标索引获取
{
for(int i =0;i<FileExtList.Count;i++)
{
if (fileName == FileExtList[i])
{
index = i;
break;
}
}
if (index > 0)
{
}
else
{
addFileIcon(fileName);//装载图标到ImageList中
index = smallImageList.Images.Count - 1;
FileExtList.Add(fileName);
}
}
return index;
}