我试图在文件夹system32中获取文件和文件夹的图标,但在不同的文件上获取"System.ArgumentException" in System.Drawing.dll
。
我创建了一个类:
[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;
}
class Win32
{
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("gdi32.dll", SetLastError = true)]
public static extern bool DeleteObject(IntPtr hObject);
}
获取图标:
private Icon GetIcon(string filePatch)
{
Icon icon;
SHFILEINFO shinfo = new SHFILEINFO();
IntPtr hIconSmall = Win32.SHGetFileInfo(filePatch, 0, ref shinfo, /*(uint)Marshal.SizeOf(shinfo)*/ 80, Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON);
if (hIconSmall == IntPtr.Zero)
{
icon = iconUnknown;
}
else
{
icon = Icon.FromHandle(shinfo.hIcon);
//"System.ArgumentException" in System.Drawing.dll
}
Win32.DeleteObject(shinfo.hIcon);
return (icon);
}
我知道我需要DeleteObject
,但这似乎不会发生。我做错了什么?
PS:在属性项目中,我检查Any CPU
答案 0 :(得分:0)
// I got a form with a virtual listview and a icon list
// there may be some mistakes I had to edit it together
public class DirContent // directory content like one file or one folder
{
public string Name;
public string Path;
public string Modyfied;
public string Extention;
public string Size;
}
public class DirectoryContent //this contains a list with mulyble files and folders and the previous folder and selected folder
{
public List<DirContent> dirContent = new List<DirContent>();
public string previousDirectory;
public string selectedDirectory;
}
public partial class Form1 : Form
{
static Dictionary<string, int> IconDictornary = new Dictionary<string, int>(); //this is a Dictionary to keep track of the loaded files;
static DirContent directoryContent = // file to load the icon for
public Form1()
{
}
private void Form1_Load(object sender, EventArgs e)
{
Icon icon = Icon.ExtractAssociatedIcon(@"path/to/file/file.png");
icons.Images.Add("empty", icon); // add empty file icon to imageList of form; (index 1) (index 0 = folder icon) i set that in imagelist propperites
}
public void getFileIcon() // I had a list view and had to cut out some things to show only the usefull stuf
{
// I had a virtual list view it much better for rendering. The system32 folder contains allot of files. so this is a handy thing
int index;
if (itemIndex == 0) // i checked if the index of te listview item that has to render == 0;
{
ListViewItem parrentItem = new ListViewItem("", 0);
parrentItem.SubItems.Add("..");
parrentItem.SubItems.Add("");
parrentItem.SubItems.Add("");
listview[itemIndex].Item = parrentItem;
// set on index 0 of list view a .. for previous folder
}
else
{
if (IconDictornary.ContainsKey(directoryContent[ItemIndex].Extention)) // If the icon already loaded in to IconDictornary get the key that wil be presented by the index of the icon in the icon list;
{
index = IconDictornary[directoryContent[ItemIndex].Extention];
}
else
{
index = GetIconIndexFromIcon(directoryContent[ItemIndex].Extention); // get File/folder icon
}
ListViewItem lvi = new ListViewItem("", index); // image index of icon in icon list
lvi.SubItems.Add(directoryContent[ItemIndex].Name);
lvi.SubItems.Add(directoryContent[ItemIndex].Modyfied);
lvi.SubItems.Add(directoryContent[ItemIndex].Size);
listview[itemIndex].Item = lvi;
// set details for sub items and show it to list view
}
}
private int GetIconIndexGetIcon(string extention)
{
Icon icon;
int index = 0;
try
{
if (extention == ".folder") // i check if the file extention = .folder if yes index = 0; iconlist[0] == folder. as I sayd above
{
index = 0;
}
else
{
icon = Icons.IconFromExtension(extention, Icons.SystemIconSize.Large); // get icon by extention
icons.Images.Add(extention, icon); // add to icon list with key, icon
index = icons.Images.IndexOfKey(extention);
IconDictornary.Add(extention, index); // set loaded file to IconDictornary by extention and index from the icon list
}
}
catch
{
index = 1;
}
return index; // return index where to find icon
}
}
我用来获取图标的方法:
public static Icon IconFromExtension(string extension,
SystemIconSize size)
{
try
{
// 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]);
}
catch (Exception ex)
{
return null;
}
}
需要包括Dll:
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;
};
[Flags]
enum FileInfoFlags : int
{
SHGFI_ICON = 0x000000100,
SHGFI_USEFILEATTRIBUTES = 0x000000010
}
[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);