Три часа утра, разгребаю почту скопившуюся за день и натыкаюсь на письмо с вопросом о том, как получить иконку для файла с определенным расширением. Первой мыслью было - сказать о WinAPI функции ExtractIcon и пойти спать, но почему-то эта мысль не победила желание написать пару строк кода.
Я быстренько накидал вот такой прототип:
(использую Zoom для растягивания элемента в Picture).
Для этого интерфейса создаю коллекцию объектов FileIcon описанных ниже и привязываю к форме:
private void FormMain_Load(object sender, EventArgs e) { FileIcons.FileIconCollection col = FileIconCollection.GetSystemFileIcons(); extCombo.DataSource = col.FileIcons;
}
private void extCombo_SelectedIndexChanged(object sender, EventArgs e) { extPicture.Image = ((FileIcon)extCombo.SelectedItem).Icon.ToBitmap(); }
Сами объекты:
public class FileIcon { public Icon Icon { get; set;} public string FileExtension { get; set;}
public override string ToString() { return FileExtension; } }
Самое интересное - как получить коллекцию. На самом деле это очень просто - вся информация о привязаных к определенному расширению файла иконках храниться в реестре в ветке HKEY_CLASSES_ROOT, вот оттуда их можно и вытащить, а с помощью ExtractIcon получить саму иконку. Код очень простой:
public class FileIconCollection {
// WinAPI function [DllImport("shell32.dll", EntryPoint = "ExtractIconA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern IntPtr ExtractIcon(int hInst, string lpszExeFileName, int nIconIndex);
public List<FileIcon> FileIcons { get; private set; }
private FileIconCollection() { }
private static Icon GetIcon(string iconPath) { int strIndex = iconPath.IndexOf(","); string iconFileName = (strIndex > 0) ? iconPath.Substring(0, strIndex) : iconPath; int iconFileIndex;
int.TryParse(iconPath.Substring(strIndex + 1), out iconFileIndex);
// Grab icon handle IntPtr hIcon = ExtractIcon(0, iconFileName, iconFileIndex);
return (hIcon != IntPtr.Zero) ? Icon.FromHandle(hIcon) : null;
public static FileIconCollection GetSystemFileIcons() {
List<FileIcon> list = new List<FileIcon>();
RegistryKey extRoot = Registry.ClassesRoot;
foreach (string key in extRoot.GetSubKeyNames()) { // skip if it is non file extension key if (String.IsNullOrEmpty(key) || (key.IndexOf(".") != 0)) continue;
RegistryKey extKey = extRoot.OpenSubKey(key);
// skip if no such element if ((extKey == null) || (extKey.GetValue("") == null)) continue;
// get sub key string iconKey = String.Format("{0}\\DefaultIcon", extKey.GetValue(""));
RegistryKey extIcon = extRoot.OpenSubKey(iconKey);
// skip if no such element if ((extIcon == null) || (extIcon.GetValue("") == null)) continue;
FileIcon fi = new FileIcon { FileExtension = key, Icon = GetIcon(extIcon.GetValue("").ToString()) }; extIcon.Close(); list.Add(fi); }
extRoot.Close();
return new FileIconCollection { FileIcons = list }; } }
Надеюсь, что несмотря на позднее время (или очень раннее) код понятен. Прицепил исходный код в виде solution для VS2008.