Ответ 1
Вы можете использовать Icon.ExtractAssociatedIcon гораздо более простой (управляемый) подход, чем использование SHGetFileInfo. Но обратите внимание: у двух файлов с одинаковым расширением могут быть разные значки.
первый вопрос здесь. Я разрабатываю программу на С# (.NET 3.5), которая отображает файлы в списке. Я хотел бы, чтобы в представлении "большой значок" отображался значок, который использует проводник Windows для этого типа файлов, в противном случае мне придется использовать какой-то существующий код:
private int getFileTypeIconIndex(string fileName)
{
string fileLocation = Application.StartupPath + "\\Quarantine\\" + fileName;
FileInfo fi = new FileInfo(fileLocation);
switch (fi.Extension)
{
case ".pdf":
return 1;
case ".doc": case ".docx": case ".docm": case ".dotx":case ".dotm": case ".dot":case ".wpd": case ".wps":
return 2;
default:
return 0;
}
}
Вышеприведенный код возвращает целое число, которое используется для выбора значка из imagelist, который я заполнял некоторыми обычными значками. Он отлично работает, но мне нужно добавить каждое расширение под солнцем! Есть ли способ лучше? Спасибо!
Вы можете использовать Icon.ExtractAssociatedIcon гораздо более простой (управляемый) подход, чем использование SHGetFileInfo. Но обратите внимание: у двух файлов с одинаковым расширением могут быть разные значки.
Значки файлов хранятся в реестре. Это немного запутанно, но он работает что-то вроде
Существует несколько примеров кода на CodeProject
Я использовал следующее решение из codeproject в одном из моих последних проектов
Получение (и управление) значков файлов и папок с помощью SHGetFileInfo в С#
Демонстрационный проект довольно понятен, но в основном вам просто нужно:
private System.Windows.Forms.ListView FileView;
private ImageList _SmallImageList = new ImageList();
private ImageList _LargeImageList = new ImageList();
private IconListManager _IconListManager;
в конструкторе:
_SmallImageList.ColorDepth = ColorDepth.Depth32Bit;
_LargeImageList.ColorDepth = ColorDepth.Depth32Bit;
_SmallImageList.ImageSize = new System.Drawing.Size(16, 16);
_LargeImageList.ImageSize = new System.Drawing.Size(32, 32);
_IconListManager = new IconListManager(_SmallImageList, _LargeImageList);
FileView.SmallImageList = _SmallImageList;
FileView.LargeImageList = _LargeImageList;
а затем, наконец, при создании ListViewItem:
ListViewItem item = new ListViewItem(file.Name, _IconListManager.AddFileIcon(file.FullName));
Работал отлично для меня.
Изменить: Здесь - это версия без PInvoke.
[StructLayout(LayoutKind.Sequential)]
public 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;
};
public const uint SHGFI_ICON = 0x100;
public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
public const uint SHGFI_SMALLICON = 0x1; // 'Small icon
[DllImport("shell32.dll")]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
[DllImport("User32.dll")]
public static extern int DestroyIcon(IntPtr hIcon);
public static System.Drawing.Icon GetSystemIcon(string sFilename)
{
//Use this to get the small Icon
IntPtr hImgSmall; //the handle to the system image list
//IntPtr hImgLarge; //the handle to the system image list
APIFuncs.SHFILEINFO shinfo = new APIFuncs.SHFILEINFO();
hImgSmall = APIFuncs.SHGetFileInfo(sFilename, 0, ref shinfo,
(uint)Marshal.SizeOf(shinfo), APIFuncs.SHGFI_ICON | APIFuncs.SHGFI_SMALLICON);
//Use this to get the large Icon
//hImgLarge = SHGetFileInfo(fName, 0,
// ref shinfo, (uint)Marshal.SizeOf(shinfo),
// Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON);
//The icon is returned in the hIcon member of the shinfo struct
System.Drawing.Icon myIcon = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shinfo.hIcon).Clone();
DestroyIcon(shinfo.hIcon); // Cleanup
return myIcon;
}