当前位置:  开发笔记 > 编程语言 > 正文

如何在C#中获取常见的文件类型图标?

如何解决《如何在C#中获取常见的文件类型图标?》经验,为你挑选了3个好方法。

正如在这个关于获取常见文件类型图标的问题中所看到的,Windows程序很可能使用C++ Shell API获取已注册文件类型的图标.这些图标可能存在于磁盘上,也可能不存在 - 例如,我们想要创建自己的自定义文件浏览器,并希望在文件中显示与系统相关的图标.

是否有本地C#方式获取各种文件类型的图标(如果是,如何)或必须通过带有shell API的PInvoke来完成?

作为后续工作,如果有一种原生的.NET方式,那么有没有跨平台的方式呢?



1> Julien Ronca..:

我的一个旧的开源项目包括一个完全相同的Icon类,随意撕开它,看到我把这个文件放在公共领域的年龄无论如何它只是PInvoke大部分.

要获取您使用的图标,例如:

Icon zipIcon = BlackFox.Win32.Icons.IconFromExtension(".zip", SystemIconSize.Small);

完整样本:

using System;
using System.Windows.Forms;
using BlackFox.Win32;
using System.Drawing;

class Program
{
    static void Main(string[] args)
    {
        PictureBox pict = new PictureBox();
        pict.Image = Icons.IconFromExtension(".zip", Icons.SystemIconSize.Large).ToBitmap();
        pict.Dock = DockStyle.Fill;
        pict.SizeMode = PictureBoxSizeMode.CenterImage;

        Form form = new Form();
        form.Controls.Add(pict);

        Application.Run(form);        
    }
}

图书馆 :

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Reflection;
using System.Collections.Generic;

namespace BlackFox.Win32
{
    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

        /// 
        /// Contains information about a file object. 
        /// 
        struct SHFILEINFO
        {
            /// 
            /// Handle to the icon that represents the file. You are responsible for
            /// destroying this handle with DestroyIcon when you no longer need it. 
            /// 
            public IntPtr hIcon;

            /// 
            /// Index of the icon image within the system image list.
            /// 
            public IntPtr iIcon;

            /// 
            /// Array of values that indicates the attributes of the file object.
            /// For information about these values, see the IShellFolder::GetAttributesOf
            /// method.
            /// 
            public uint dwAttributes;

            /// 
            /// 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.
            /// 
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;

            /// 
            /// String that describes the type of file.
            /// 
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        };

        [Flags]
        enum FileInfoFlags : int
        {
            /// 
            /// 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.
            /// 
            SHGFI_ICON = 0x000000100,
            /// 
            /// 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.
            /// 
            SHGFI_USEFILEATTRIBUTES = 0x000000010
        }

        /// 
        ///     Creates an array of handles to large or small icons extracted from
        ///     the specified executable file, dynamic-link library (DLL), or icon
        ///     file. 
        /// 
        /// 
        ///     Name of an executable file, DLL, or icon file from which icons will
        ///     be extracted.
        /// 
        /// 
        ///     
        ///         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.
        ///     
        ///     
        ///         If this value is ?1 and  and
        ///          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. 
        ///     
        ///     
        ///         Windows 95/98/Me, Windows NT 4.0 and later: If this value is a 
        ///         negative number and either  or 
        ///          is not NULL, the function begins by
        ///         extracting the icon whose resource identifier is equal to the
        ///         absolute value of . For example, use -3
        ///         to extract the icon whose resource identifier is 3. 
        ///     
        /// 
        /// 
        ///     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.
        /// 
        /// 
        ///     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. 
        /// 
        /// 
        ///     Specifies the number of icons to extract from the file. 
        /// 
        /// 
        ///     If the  parameter is -1, the
        ///      parameter is NULL, and the
        ///      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. 
        /// 
        [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

        /// 
        /// Two constants extracted from the FileInfoFlags, the only that are
        /// meaningfull for the user of this class.
        /// 
        public enum SystemIconSize : int
        {
            Large = 0x000000000,
            Small = 0x000000001
        }

        /// 
        /// Get the number of icons in the specified file.
        /// 
        /// Full path of the file to look for.
        /// 
        static int GetIconsCountInFile(string fileName)
        {
            return ExtractIconEx(fileName, -1, null, null, 0);
        }

        #region ExtractIcon-like functions

        public static void ExtractEx(string fileName, List largeIcons,
            List 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 ExtractEx(string fileName, SystemIconSize size,
            int firstIconIndex, int iconCount)
        {
            List iconList = new List();

            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 largeIcons, List smallIcons)
        {
            int iconCount = GetIconsCountInFile(fileName);
            ExtractEx(fileName, largeIcons, smallIcons, 0, iconCount);
        }

        public static List 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 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 smallIconList = new List();
            List largeIconList = new List();
            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));
        }

        /// 
        /// Parse strings in registry who contains the name of the icon and
        /// the index of the icon an return both parts.
        /// 
        /// The full string in the form "path,index" as found in registry.
        /// The "path" part of the string.
        /// The "index" part of the string.
        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);
        }
    }
}


@VirtualBlackFox:你暗示它是意大利面条代码吗?(*呻吟*)

2> Gabriël..:

请查看:http://mvolo.com/display-pretty-file-icons-in-your-aspnet-applications-with-iconhandler/

这不是最干净的解决方案,但它有效.否则,请尝试使用基于mime类型或文件扩展名的图标库.


链接坏了.获得403禁止.尝试http://mvolo.com/display-pretty-file-icons-in-your-aspnet-applications-with-iconhandler/

3> 小智..:

我相信你已经为你的问题找到了解决方案,但为了其他人的利益,我对VirtualBlackFox的解决方案进行了一些修改.

只需替换IconFromExtension方法......

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());

        RegistryKey CurrentVer = null;
        try
        {
            CurrentVer = Root.OpenSubKey(ApplicationKey.OpenSubKey("CurVer").GetValue("").ToString());
        }
        catch (Exception ex)
        {
            //current version not found... carry on without it?
        }

        if (CurrentVer != null)
            ApplicationKey = CurrentVer;

        //gets the name of the file that have the icon.
        string IconLocation =
            ApplicationKey.OpenSubKey("DefaultIcon").GetValue("").ToString();
        string[] IconPath = IconLocation.Split(',');


        IntPtr[] Large = null;
        IntPtr[] Small = null;
        int iIconPathNumber = 0;

        if (IconPath.Length > 1)
            iIconPathNumber = 1;
        else
            iIconPathNumber = 0;


        if (IconPath[iIconPathNumber] == null) IconPath[iIconPathNumber] = "0";
        Large = new IntPtr[1];
        Small = new IntPtr[1];



        //extracts the icon from the file.
        if (iIconPathNumber > 0)
        {
            ExtractIconEx(IconPath[0],
                Convert.ToInt16(IconPath[iIconPathNumber]), Large, Small, 1);
        }
        else
        {
            ExtractIconEx(IconPath[0],
                Convert.ToInt16(0), Large, Small, 1);
        }


        return size == SystemIconSize.Large ?
            Icon.FromHandle(Large[0]) : Icon.FromHandle(Small[0]);
    }

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有