正如在这个问题上获得常见文件types的图标 ,它是很有可能的Windows程序使用C ++ Shell API获取注册文件types的图标。 这些图标可能存在也可能不存在于磁盘上 – 例如,我们想制作自己的自定义文件浏览器,并且想要显示与文件相关的系统图标。
是否有一个本地的C#方式来获取各种文件types的图标(如果是这样,如何),或者必须通过PInvoke与shell API来完成?
作为一个后续,如果有一个本地.NET的方式,是否有一个跨平台的方式来做到这一点?
.NET程序集:gacutil.exe中的错误? / f选项似乎没有做任何事情
我怎样才能从VB6应用程序发送消息到我的C#应用程序
.NET Windows商店数据
WPF中的应用程序级别快捷键
为什么Graphics :: DrawImage不像预期的那样拉伸图像?
对Process.Start(URL)的适当响应; 失败?
如何引用外部类中的string(C#)
最新单声道在centos上
看看: http : //mvolo.com/display-pretty-file-icons-in-your-aspnet-applications-with-iconhandler/
这不是最干净的解决方案,但它的工作原理。 否则,请尝试使用基于MIME类型或文件扩展名的图标库。
我的一个老的开源项目包括一个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 /// <summary> /// Contains @R_304_4045@ion 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 @R_304_4045@ion 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,0); } #region ExtractIcon-like functions public static void ExtractEx(string fileName,List<Icon> largeIcons,List<Icon> smallIcons,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,largeIconsPtrs,smallIconsPtrs,iconCount); if (apiResult != iconCount) { throw new UnabletoExtractIconsException(fileName,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 iconCount) { List<Icon> iconList = new List<Icon>(); switch (size) { case SystemIconSize.Large: ExtractEx(fileName,iconList,iconCount); break; case SystemIconSize.Small: ExtractEx(fileName,iconCount); break; default: throw new ArgumentOutOfRangeException("size"); } return iconList; } public static void Extract(string fileName,List<Icon> smallIcons) { int iconCount = GetIconsCountInFile(fileName); ExtractEx(fileName,largeIcons,smallIcons,iconCount); } public static List<Icon> Extract(string fileName,SystemIconSize size) { int iconCount = GetIconsCountInFile(fileName); return ExtractEx(fileName,size,iconCount); } public static Icon ExtractOne(string fileName,int index,SystemIconSize size) { try { List<Icon> iconList = ExtractEx(fileName,1); return iconList[0]; } catch (UnabletoExtractIconsException) { throw new IconNotFoundException(fileName,index); } } public static void ExtractOne(string fileName,out Icon largeIcon,out Icon smallIcon) { List<Icon> smallIconList = new List<Icon>(); List<Icon> largeIconList = new List<Icon>(); try { ExtractEx(fileName,largeIconList,smallIconList,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,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 Extract@R_304_4045@ionsFromregistryString( 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; Extract@R_304_4045@ionsFromregistryString(regString,out fileName,out index); return ExtractOne(fileName,size); } } }
我相信你已经找到了解决问题的办法,但为了别人的利益,我对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]),1); } else { ExtractIconEx(IconPath[0],Convert.ToInt16(0),1); } return size == SystemIconSize.Large ? Icon.FromHandle(Large[0]) : Icon.FromHandle(Small[0]); }
Icon.ExtractAssociatedIcon()不会做的伎俩。 正如MSDN所说,它只提取文件中包含的图标。 所以创建虚拟文件也无济于事。 据我所知,你必须去p / invoke的方式来获得这些图标。 与此有关的一个问题是这个 。 MaLio似乎有一个相当完整的例子,如何使用p / invoke获取图标。
我不知道一个平台不可知的方式来做到这一点(我不认为有一个)。
抱歉,我无法为您提供更好的消息!
这个班应该做这个工作。 传递文件名(带路径)或文件夹名称(带路径)。
public static class FileIcon { [DllImport("shell32.dll")] private static extern IntPtr SHGetFileInfo(string pszPath,uint dwFileAttributes,ref SHFILEINFO psfi,uint cbSizefileInfo,uint uFlags); [StructLayout(LayoutKind.Sequential)] 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; }; private const uint SHGFI_ICON = 0x100; private const uint SHGFI_LARGEICON = 0x0; // 'Large icon private const uint SHGFI_SMALLICON = 0x1; // 'Small icon public static System.Drawing.Icon GetLargeIcon(string file) { FileIcon.SHFILEINFO shinfo = new FileIcon.SHFILEINFO(); IntPtr hImgLarge = FileIcon.SHGetFileInfo(file,ref shinfo,(uint)Marshal.SizeOf(shinfo),FileIcon.SHGFI_ICON | FileIcon.SHGFI_LARGEICON); return System.Drawing.Icon.FromHandle(shinfo.hIcon); } public static System.Drawing.Icon GetSmallIcon(string file) { FileIcon.SHFILEINFO shinfo = new FileIcon.SHFILEINFO(); IntPtr hImgLarge = FileIcon.SHGetFileInfo(file,FileIcon.SHGFI_ICON | FileIcon.SHGFI_SMALLICON); return System.Drawing.Icon.FromHandle(shinfo.hIcon); } }
可以使用IQueryAssociations接口来代替浏览注册表。 这个接口也可以用来获得更多关于注册文件类型的信息(参见ie ASSOCSTR类型)。 下面我附上代码,它取代了VirtualBlackFox解决方案中的IconFromExtension方法(部分代码保持不变):
public static Icon IconFromExtension(string extension,SystemIconSize size) { if (extension[0] != '.') extension = '.' + extension; object obj; shell.AssocCreate(shell.CLSID_QueryAssociations,ref shell.IID_IQueryAssociations,out obj); var qa = (shell.IQueryAssociations)obj; qa.Init(shell.ASSOCF.INIT_DEFAULTTOSTAR,Convert.ToString(extension),UIntPtr.Zero,IntPtr.Zero); var bufSize = 0; qa.GetString(shell.ASSOCF.NOTruncATE,shell.ASSOCSTR.DEFAULTICON,ref bufSize); var sb = new StringBuilder(bufSize); qa.GetString(shell.ASSOCF.NOTruncATE,sb,ref bufSize); if (!String.IsNullOrEmpty(sb.ToString())) { var iconLocation = sb.ToString(); var iconPath = iconLocation.Split(','); var iIconPathNumber = iconPath.Length > 1 ? 1 : 0; if (iconPath[iIconPathNumber] == null) iconPath[iIconPathNumber] = "0"; var large = new IntPtr[1]; var small = new IntPtr[1]; //extracts the icon from the file. ExtractIconEx(iconPath[0],iIconPathNumber > 0 ? Convert.ToInt16(iconPath[iIconPathNumber]) : Convert.ToInt16(0),large,small,1); return size == SystemIconSize.Large ? Icon.FromHandle(large[0]) : Icon.FromHandle(small[0]); } return IntPtr.Zero; }
除了上面的代码外,还需要一个“shell”类 – Shell API的一个包装器(下面仅限于AssocCreate和必要的类型):
using System; using System.Runtime.InteropServices; using System.Text; #pragma warning disable 1591 // ReSharper disable InconsistentNaming namespace <put_your_appropriate_namespace_here> { public class shell { [DllImport("shlwapi.dll")] public extern static int AssocCreate( Guid clsid,ref Guid riid,[MarshalAs(UnmanagedType.Interface)] out object ppv); [Flags] public enum ASSOCF { INIT_norEMAPCLSID = 0x00000001,INIT_BYEXENAME = 0x00000002,OPEN_BYEXENAME = 0x00000002,INIT_DEFAULTTOSTAR = 0x00000004,INIT_DEFAULTTOFOLDER = 0x00000008,NOUSERSETTINGS = 0x00000010,NOTruncATE = 0x00000020,VERIFY = 0x00000040,REMAPRUNDLL = 0x00000080,NOFIXUPS = 0x00000100,IGnorEBASECLASS = 0x00000200,INIT_IGnorEUNKNowN = 0x00000400 } public enum ASSOCSTR { COMMAND = 1,EXECUTABLE,FRIENDLYDOCNAME,FRIENDLYAPPNAME,NOOPEN,SHELLNEWVALUE,DDECOMMAND,DDEIFEXEC,DDEAPPLICATION,DDetoPIC,INFOTIP,QUICKTIP,TILEINFO,CONTENTTYPE,DEFAULTICON,SHELLEXTENSION } public enum ASSOCKEY { SHELLEXEcclASS = 1,APP,CLASS,BASECLASS } public enum ASSOCDATA { MSIDESCRIPTOR = 1,NOACTIVATEHANDLER,QUERYCLASsstORE,HASPERUSERASSOC,EDITFLAGS,VALUE } [Guid("c46ca590-3c3f-11d2-bee6-0000f805ca57"),InterfaceType(ComInterfaceType.InterfaceIsIUnkNown)] public interface IQueryAssociations { void Init( [In] ASSOCF flags,[In,MarshalAs(UnmanagedType.LPWStr)] string pszAssoc,[In] UIntPtr hkProgid,[In] IntPtr hwnd); void GetString( [In] ASSOCF flags,[In] ASSOCSTR str,MarshalAs(UnmanagedType.LPWStr)] string pwszExtra,[Out,MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszOut,Out] ref int pcchOut); void GetKey( [In] ASSOCF flags,[In] ASSOCKEY str,[Out] out UIntPtr phkeyOut); void GetData( [In] ASSOCF flags,[In] ASSOCDATA data,MarshalAs(UnmanagedType.LPArray,SizeParamIndex = 4)] out byte[] pvOut,Out] ref int pcbOut); void GetEnum(); // not used actually } public static Guid CLSID_QueryAssociations = new Guid("a07034fd-6caa-4954-ac3f-97a27216f98a"); public static Guid IID_IQueryAssociations = new Guid("c46ca590-3c3f-11d2-bee6-0000f805ca57"); } }
对于需要ImageSource的WPF用户:
将图标的返回类型替换为ImageSource,将return子句替换为:
var iconPtr = size == SystemIconSize.Large ? large[0] : small[0]; if (iconPtr != IntPtr.Zero) { return Imaging.CreateBitmapSourceFromHIcon( iconPtr,Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions()); }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。