Получение иконки, ассоциированной с некоторым типом файла
Три часа утра, разгребаю почту скопившуюся за день и натыкаюсь на письмо с вопросом о том, как получить иконку для файла с определенным расширением. Первой мыслью было - сказать о 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.
Comments
Anonymous
November 21, 2008
в коде не обрабатывается NULL для иконок ;)Anonymous
November 21, 2008
Дык прототип же :). На будущее учту такого не публиковать.