上篇关于带图标显示菜单的实现办法中大家可以看到我把文件以及文件夹的图标显示在菜单项上,就像在资源管理器中一样。

    那个图标是怎么获取的呢,我在MSDN中搜索了一下,找到了SHGetFileInfo函数,这是Shell32.dll中的一个函数,具体功能大家还是看MSDN中Platform SDK部分对SHGetFileInfo函数的说明,在这里很难全部都做说明。以下只介绍下我的做法,以及对所遇到的问题的解决方式。

    阅读以下部分前请先浏览:
    MSDN中Platform SDK部分对SHGetFileInfo函数的说明

    SHGetFileInfo函数的大部分参数都是简单的数值类型参数,唯一让我不太明白的是psfi参数,这个参数是一个SHFILEINFO结构体指针,C#中要怎么传这样一个结构体进去呢?我查看了MSDN中.NET框架部分关于封送类、结构和联合的资料,里面提到了使用ref关键字进行结构体的引用传递,所以我将SHGetFileInfo函数声明为如下格式:

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

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

1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        
[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类中,代码我会放在文章的最后部分以防止大家阅读文章不便。

    最后我在我的文件浏览菜单项中定义了一个静态方法来获取文件夹或者文件的小图标,代码如下:

1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        
///<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类代码

1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        
///<summary>  
        /// 获取文件系统中对象的信息,例如:文件、文件夹、驱动器根目录 
        ///</summary>   
        public class FileInfo
        {
        [DllImport("shell32.dll", EntryPoint="SHGetFileInfo")]
        public static extern int 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 
        }
        }
posted on 2009-07-28 13:40  赵保龙  阅读(609)  评论(0)    收藏  举报