上篇关于带图标显示菜单的实现办法中大家可以看到我把文件以及文件夹的图标显示在菜单项上,就像在资源管理器中一样。 
  那个图标是怎么获取的呢,我在MSDN中搜索了一下,找到了SHGetFileInfo函数,这是Shell32.dll中的一个函数,具体功能大家还是看MSDN中Platform SDK部分对SHGetFileInfo函数的说明,在这里很难全部都做说明。一下只介绍下我的做法,以及对所遇到的问题的解决方式。 
  阅读以下部分前请先浏览:
  MSDN中Platform SDK部分对SHGetFileInfo函数的说明
  SHGetFileInfo函数的大部分参数都是简单的数值类型参数,唯一让我不太明白的是psfi参数,这个参数是一个SHFILEINFO结构体指针,C#中要怎么传这样一个结构体进去呢?我查看了MSDN中.NET框架部分关于封送类、结构和联合的资料,里面提到了使用ref关键字进行结构体的引用传递,所以我将SHGetFileInfo函数声明为如下格式: 

 

[DllImport("shell32.dll", EntryPoint="SHGetFileInfo")] 
 public static extern int GetFileInfo
 (string pszPath, int dwFileAttributes, ref FileInfomation psfi, int cbFileInfo,int uFlags);

并根据MSDN中对SHFILEINFO结构体的定义声明了它的C#版本: 

[ StructLayout( LayoutKind.Sequential)] 
  public   struct  FileInfomation 
   { 
       public  IntPtr hIcon; 
       public   int  iIcon; 
       public   int  dwAttributes;      [ MarshalAs( UnmanagedType.ByValTStr, SizeConst = 260 )] 
       public   string  szDisplayName;      [ MarshalAs( UnmanagedType.ByValTStr, SizeConst = 80 )] 
       public   string  szTypeName; 
  }

MarshalAs( UnmanagedType.ByValTStr, SizeConst=260)标签可以在MSDN关于封送类、结构和联合的资料中找到。 

搜索了一下Platform SDK的头文件,在ShellApi.h中找到了uFlags的定义,我将这些值声明为GetFileInfoFlags枚举类型(详细代码在后面),我目前只用到了SHGFI_ICON和SHGFI_SMALLICON,SHGFI_ICON表示要获取文件大图标,SHGFI_SMALLICON表示要获取小图标,我第一次用SHGFI_SMALLICON时程序出现了异常,后来仔细看MSDN才知道SHGFI_SMALLICON和SHGFI_ICON必须要连用。 
 
最后我把这些API函数声明、结构体声明、枚举类型声明等东西总的放在一个FileInfo类中,代码我会放在文章的最后部分以防止大家阅读文章不便。
 
最后我在我的文件浏览菜单项中定义了一个静态方法来获取文件夹或者文件的小图标,代码如下: 

/**/ ///   <summary>  
   ///  通过路径获取小图标 
   ///   </summary>  
   ///   <param name="path"> 文件或文件夹路径 </param>  
   ///   <returns> 获取的图标 </returns>   
    public   static  Icon GetSmallIcon( string  path) 
   { 
      FileInfo.FileInfomation _info  = new  System.FileInfo.FileInfomation();      FileInfo.GetFileInfo(path,  0 ,  ref  _info, Marshal.SizeOf(_info), 
      ( int )(FileInfo.GetFileInfoFlags.SHGFI_ICON | FileInfo.GetFileInfoFlags.SHGFI_SMALLICON)); 
       try 
         { 
           return  Icon.FromHandle(_info.hIcon); 
      } 
       catch 
         { 
           return   null ; 
      } 
  }

大家可以拿一段代码时候试试看,比图将C盘根目录图标显示在PictureBox里: 

pictureBox.Image = GetSmallIcon("C:\\");
  
 FileInfo类代码 
   /**/ ///   <summary>  
   ///  获取文件系统中对象的信息,例如:文件、文件夹、驱动器根目录 
   ///   </summary>   
    public   class  FileInfo 
   { 
      [DllImport( " shell32.dll " , EntryPoint = " SHGetFileInfo " )] 
      publicstaticexternint GetFileInfo( string  pszPath,  int  dwFileAttributes, 
       ref  FileInfomation psfi,  int  cbFileInfo, int  uFlags);  private  FileInfo()  {} 
  
      [ StructLayout( LayoutKind.Sequential)] 
       public   struct  FileInfomation 
        { 
           public  IntPtr hIcon; 
           public   int  iIcon; 
           public   int  dwAttributes; 
          [ MarshalAs( UnmanagedType.ByValTStr, SizeConst = 260 )] 
           public   string  szDisplayName; 
          [ MarshalAs( UnmanagedType.ByValTStr, SizeConst = 80 )] 
           public   string  szTypeName; 
      } 
       public   enum  FileAttributeFlags :  int 
         { 
          FILE_ATTRIBUTE_READONLY  = 0x00000001 , 
          FILE_ATTRIBUTE_HIDDEN  = 0x00000002 , 
          FILE_ATTRIBUTE_SYSTEM  = 0x00000004 , 
          FILE_ATTRIBUTE_DIRECTORY  = 0x00000010 , 
          FILE_ATTRIBUTE_ARCHIVE  = 0x00000020 , 
          FILE_ATTRIBUTE_DEVICE  = 0x00000040 , 
          FILE_ATTRIBUTE_NORMAL  = 0x00000080 , 
          FILE_ATTRIBUTE_TEMPORARY  = 0x00000100 , 
          FILE_ATTRIBUTE_SPARSE_FILE  = 0x00000200 , 
          FILE_ATTRIBUTE_REPARSE_POINT  = 0x00000400 , 
          FILE_ATTRIBUTE_COMPRESSED  = 0x00000800 , 
          FILE_ATTRIBUTE_OFFLINE  = 0x00001000 , 
          FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  = 0x00002000 , 
          FILE_ATTRIBUTE_ENCRYPTED  = 0x00004000  
      } 
       public   enum  GetFileInfoFlags :  int 
         { 
          SHGFI_ICON  = 0x000000100 ,  //  get icon 
           SHGFI_DISPLAYNAME  = 0x000000200 ,  //  get display name 
           SHGFI_TYPENAME  = 0x000000400 ,  //  get type name 
           SHGFI_ATTRIBUTES  = 0x000000800 ,  //  get attributes 
           SHGFI_ICONLOCATION  = 0x000001000 ,  //  get icon location 
           SHGFI_EXETYPE  = 0x000002000 ,  //  return exe type 
           SHGFI_SYSICONINDEX  = 0x000004000 ,  //  get system icon index 
           SHGFI_LINKOVERLAY  = 0x000008000 ,  //  put a link overlay on icon 
           SHGFI_SELECTED  = 0x000010000 ,  //  show icon in selected state 
           SHGFI_ATTR_SPECIFIED  = 0x000020000 ,  //  get only specified attributes 
           SHGFI_LARGEICON  = 0x000000000 ,  //  get large icon 
           SHGFI_SMALLICON  = 0x000000001 ,  //  get small icon 
           SHGFI_OPENICON  = 0x000000002 ,  //  get open icon 
           SHGFI_SHELLICONSIZE  = 0x000000004 ,  //  get shell size icon 
           SHGFI_PIDL  = 0x000000008 ,  //  pszPath is a pidl 
           SHGFI_USEFILEATTRIBUTES  = 0x000000010 ,  //  use passed dwFileAttribute 
           SHGFI_ADDOVERLAYS  = 0x000000020 ,  //  apply the appropriate overlays 
           SHGFI_OVERLAYINDEX  = 0x000000040   //  Get the index of the overlay 
       } 
  }