在Winform开发中,大家普遍利用Listview来显示文件列表。 但是Listview本身并不具备显示当前系统图标的功能。所以要想实现类似的功能,需要利用Icon和Imagelist来辅助。
1, 实例一个imagelist作为图标管理容器。
2, 根据文件绝对路径将对应的系统图标加入imagelist
3, 将listview的显示属性View修改为:SmallIcon
4, 获取对应图标的index 并赋值给ListViewItem
源代码如下:
using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace ListViewDemo { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { listView1.Items.Clear(); string DemoFolder = "c:\\listview"; DirectoryInfo di = new DirectoryInfo(DemoFolder); //get all fileinfo in the demo folder foreach (FileInfo f in di.GetFiles()) { //add system icon of current file into imagelist if (!imageList1.Images.Keys.Contains(f.Extension)) { imageList1.Images.Add(f.Extension, Icon.ExtractAssociatedIcon(f.FullName)); } ListViewItem lvi = new ListViewItem(); lvi.Text = f.Name; //get imageindex from imagelist according to the file extension lvi.ImageIndex = imageList1.Images.Keys.IndexOf(f.Extension); listView1.Items.Add(lvi); } } } }效果图:
对于一些非当前系统中的文件,如果没有文件绝对路径,只知道文件扩展名,就需要再添加一个自定义的类。 根据文件扩展名来获取对应的图标。
1, 获取文件扩展名,
2,根据文件扩展名来获取系统图标,
3, 将listview的显示属性View修改为:SmallIcon
4, 获取对应图标的index 并赋值给ListViewItem
首先是自定义的类:
using System; using System.Drawing; using System.Runtime.InteropServices; using Microsoft.Win32; using System.Reflection; using System.Collections.Generic; namespace ALM_Resource_Sync.Lib { public static class Icons { #region Custom exceptions class public class IconNotFoundException : Exception { public IconNotFoundException(string fileName, int index) : base(string.Format("Icon with Id = {0} wasn't found in file {1}", index, fileName)) { } } public class UnableToExtractIconsException : Exception { public UnableToExtractIconsException(string fileName, int firstIconIndex, int iconCount) : base(string.Format("Tryed to extract {2} icons starting from the one with id {1} from the \"{0}\" file but failed", fileName, firstIconIndex, iconCount)) { } } #endregion #region DllImports /// <summary> /// Contains information about a file object. /// </summary> struct SHFILEINFO { /// <summary> /// Handle to the icon that represents the file. You are responsible for /// destroying this handle with DestroyIcon when you no longer need it. /// </summary> public IntPtr hIcon; /// <summary> /// Index of the icon image within the system image list. /// </summary> public IntPtr iIcon; /// <summary> /// Array of values that indicates the attributes of the file object. /// For information about these values, see the IShellFolder::GetAttributesOf /// method. /// </summary> public uint dwAttributes; /// <summary> /// String that contains the name of the file as it appears in the Microsoft /// Windows Shell, or the path and file name of the file that contains the /// icon representing the file. /// </summary> [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; /// <summary> /// String that describes the type of file. /// </summary> [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; [Flags] enum FileInfoFlags : int { /// <summary> /// Retrieve the handle to the icon that represents the file and the index /// of the icon within the system image list. The handle is copied to the /// hIcon member of the structure specified by psfi, and the index is copied /// to the iIcon member. /// </summary> SHGFI_ICON = 0x000000100, /// <summary> /// Indicates that the function should not attempt to access the file /// specified by pszPath. Rather, it should act as if the file specified by /// pszPath exists with the file attributes passed in dwFileAttributes. /// </summary> SHGFI_USEFILEATTRIBUTES = 0x000000010 } /// <summary> /// Creates an array of handles to large or small icons extracted from /// the specified executable file, dynamic-link library (DLL), or icon /// file. /// </summary> /// <param name="lpszFile"> /// Name of an executable file, DLL, or icon file from which icons will /// be extracted. /// </param> /// <param name="nIconIndex"> /// <para> /// Specifies the zero-based index of the first icon to extract. For /// example, if this value is zero, the function extracts the first /// icon in the specified file. /// </para> /// <para> /// If this value is �1 and <paramref name="phiconLarge"/> and /// <paramref name="phiconSmall"/> are both NULL, the function returns /// the total number of icons in the specified file. If the file is an /// executable file or DLL, the return value is the number of /// RT_GROUP_ICON resources. If the file is an .ico file, the return /// value is 1. /// </para> /// <para> /// Windows 95/98/Me, Windows NT 4.0 and later: If this value is a /// negative number and either <paramref name="phiconLarge"/> or /// <paramref name="phiconSmall"/> is not NULL, the function begins by /// extracting the icon whose resource identifier is equal to the /// absolute value of <paramref name="nIconIndex"/>. For example, use -3 /// to extract the icon whose resource identifier is 3. /// </para> /// </param> /// <param name="phIconLarge"> /// An array of icon handles that receives handles to the large icons /// extracted from the file. If this parameter is NULL, no large icons /// are extracted from the file. /// </param> /// <param name="phIconSmall"> /// An array of icon handles that receives handles to the small icons /// extracted from the file. If this parameter is NULL, no small icons /// are extracted from the file. /// </param> /// <param name="nIcons"> /// Specifies the number of icons to extract from the file. /// </param> /// <returns> /// If the <paramref name="nIconIndex"/> parameter is -1, the /// <paramref name="phIconLarge"/> parameter is NULL, and the /// <paramref name="phiconSmall"/> parameter is NULL, then the return /// value is the number of icons contained in the specified file. /// Otherwise, the return value is the number of icons successfully /// extracted from the file. /// </returns> [DllImport("Shell32", CharSet = CharSet.Auto)] extern static int ExtractIconEx( [MarshalAs(UnmanagedType.LPTStr)] string lpszFile, int nIconIndex, IntPtr[] phIconLarge, IntPtr[] phIconSmall, int nIcons); [DllImport("Shell32", CharSet = CharSet.Auto)] extern static IntPtr SHGetFileInfo( string pszPath, int dwFileAttributes, out SHFILEINFO psfi, int cbFileInfo, FileInfoFlags uFlags); #endregion /// <summary> /// Two constants extracted from the FileInfoFlags, the only that are /// meaningfull for the user of this class. /// </summary> public enum SystemIconSize : int { Large = 0x000000000, Small = 0x000000001 } /// <summary> /// Get the number of icons in the specified file. /// </summary> /// <param name="fileName">Full path of the file to look for.</param> /// <returns></returns> static int GetIconsCountInFile(string fileName) { return ExtractIconEx(fileName, -1, null, null, 0); } #region ExtractIcon-like functions public static void ExtractEx(string fileName, List<Icon> largeIcons, List<Icon> smallIcons, int firstIconIndex, int iconCount) { /* * Memory allocations */ IntPtr[] smallIconsPtrs = null; IntPtr[] largeIconsPtrs = null; if (smallIcons != null) { smallIconsPtrs = new IntPtr[iconCount]; } if (largeIcons != null) { largeIconsPtrs = new IntPtr[iconCount]; } /* * Call to native Win32 API */ int apiResult = ExtractIconEx(fileName, firstIconIndex, largeIconsPtrs, smallIconsPtrs, iconCount); if (apiResult != iconCount) { throw new UnableToExtractIconsException(fileName, firstIconIndex, iconCount); } /* * Fill lists */ if (smallIcons != null) { smallIcons.Clear(); foreach (IntPtr actualIconPtr in smallIconsPtrs) { smallIcons.Add(Icon.FromHandle(actualIconPtr)); } } if (largeIcons != null) { largeIcons.Clear(); foreach (IntPtr actualIconPtr in largeIconsPtrs) { largeIcons.Add(Icon.FromHandle(actualIconPtr)); } } } public static List<Icon> ExtractEx(string fileName, SystemIconSize size, int firstIconIndex, int iconCount) { List<Icon> iconList = new List<Icon>(); switch (size) { case SystemIconSize.Large: ExtractEx(fileName, iconList, null, firstIconIndex, iconCount); break; case SystemIconSize.Small: ExtractEx(fileName, null, iconList, firstIconIndex, iconCount); break; default: throw new ArgumentOutOfRangeException("size"); } return iconList; } public static void Extract(string fileName, List<Icon> largeIcons, List<Icon> smallIcons) { int iconCount = GetIconsCountInFile(fileName); ExtractEx(fileName, largeIcons, smallIcons, 0, iconCount); } public static List<Icon> Extract(string fileName, SystemIconSize size) { int iconCount = GetIconsCountInFile(fileName); return ExtractEx(fileName, size, 0, iconCount); } public static Icon ExtractOne(string fileName, int index, SystemIconSize size) { try { List<Icon> iconList = ExtractEx(fileName, size, index, 1); return iconList[0]; } catch (UnableToExtractIconsException) { throw new IconNotFoundException(fileName, index); } } public static void ExtractOne(string fileName, int index, out Icon largeIcon, out Icon smallIcon) { List<Icon> smallIconList = new List<Icon>(); List<Icon> largeIconList = new List<Icon>(); try { ExtractEx(fileName, largeIconList, smallIconList, index, 1); largeIcon = largeIconList[0]; smallIcon = smallIconList[0]; } catch (UnableToExtractIconsException) { throw new IconNotFoundException(fileName, index); } } #endregion //this will look throw the registry //to find if the Extension have an icon. public static Icon IconFromExtension(string extension, SystemIconSize size) { // Add the '.' to the extension if needed if (extension[0] != '.') extension = '.' + extension; //opens the registry for the wanted key. RegistryKey Root = Registry.ClassesRoot; RegistryKey ExtensionKey = Root.OpenSubKey(extension); ExtensionKey.GetValueNames(); RegistryKey ApplicationKey = Root.OpenSubKey(ExtensionKey.GetValue("").ToString()); //gets the name of the file that have the icon. string IconLocation = ApplicationKey.OpenSubKey("DefaultIcon").GetValue("").ToString(); string[] IconPath = IconLocation.Split(','); if (IconPath[1] == null) IconPath[1] = "0"; IntPtr[] Large = new IntPtr[1], Small = new IntPtr[1]; //extracts the icon from the file. ExtractIconEx(IconPath[0], Convert.ToInt16(IconPath[1]), Large, Small, 1); return size == SystemIconSize.Large ? Icon.FromHandle(Large[0]) : Icon.FromHandle(Small[0]); } public static Icon IconFromExtensionShell(string extension, SystemIconSize size) { //add '.' if nessesry if (extension[0] != '.') extension = '.' + extension; //temp struct for getting file shell info SHFILEINFO fileInfo = new SHFILEINFO(); SHGetFileInfo( extension, 0, out fileInfo, Marshal.SizeOf(fileInfo), FileInfoFlags.SHGFI_ICON | FileInfoFlags.SHGFI_USEFILEATTRIBUTES | (FileInfoFlags)size); return Icon.FromHandle(fileInfo.hIcon); } public static Icon IconFromResource(string resourceName) { Assembly assembly = Assembly.GetCallingAssembly(); return new Icon(assembly.GetManifestResourceStream(resourceName)); } /// <summary> /// Parse strings in registry who contains the name of the icon and /// the index of the icon an return both parts. /// </summary> /// <param name="regString">The full string in the form "path,index" as found in registry.</param> /// <param name="fileName">The "path" part of the string.</param> /// <param name="index">The "index" part of the string.</param> public static void ExtractInformationsFromRegistryString( string regString, out string fileName, out int index) { if (regString == null) { throw new ArgumentNullException("regString"); } if (regString.Length == 0) { throw new ArgumentException("The string should not be empty.", "regString"); } index = 0; string[] strArr = regString.Replace("\"", "").Split(','); fileName = strArr[0].Trim(); if (strArr.Length > 1) { int.TryParse(strArr[1].Trim(), out index); } } public static Icon ExtractFromRegistryString(string regString, SystemIconSize size) { string fileName; int index; ExtractInformationsFromRegistryString(regString, out fileName, out index); return ExtractOne(fileName, index, size); } } }
private void button2_Click(object sender, EventArgs e) { listView1.Items.Clear(); //demo file list string [] DemoFiles = {"demo.doc","demo.xls","demo.txt"}; foreach (string fileName in DemoFiles) { //get file extention string[] arrtempFileName = fileName.Split(new char[] { '.' }); string tempFileExtension = "." + arrtempFileName[arrtempFileName.Length - 1]; //add system icon of current file into imagelist if (!imageList1.Images.Keys.Contains(tempFileExtension)) { imageList1.Images.Add(tempFileExtension, Icons.IconFromExtension(tempFileExtension, Icons.SystemIconSize.Small)); } ListViewItem lvi = new ListViewItem(); lvi.Text = fileName; //get imageindex from imagelist according to the file extension lvi.ImageIndex = imageList1.Images.Keys.IndexOf(tempFileExtension); listView1.Items.Add(lvi); }
显示效果如下: