tags:

views:

1466

answers:

5

Hi all, first question here. I'm developing a program in C# (.NET 3.5) that displays files in a listview. I'd like to have the "large icon" view display the icon that Windows Explorer uses for that filetype, otherwise I'll have to use some existing code like this:

        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;
        }

    }

The above code returns an integer that is used to select an icon from an imagelist that I populated with some common icons. It works fine but I'd need to add every extension under the sun! Is there a better way? Thanks!

+4  A: 

The file icons are held in the registry. It's a little convoluted but it works something like

  • Take the file extension and lookup the registry entry for it, for example .DOC Get the default value for that registry setting, "Word.Document.8"
  • Now lookup that value in the registry.
  • Look at the default value for the "Default Icon" registry key, in this case, C:\Windows\Installer{91120000-002E-0000-0000-0000000FF1CE}\wordicon.exe,1
  • Open the file and get the icon, using any number after the comma as the indexer.

There is some sample code at on CodeProject

blowdart
A: 

My recommendation would be, to use a cache.

Robse
+7  A: 

I used the following solution from codeproject in one of recent my projects

Obtaining (and managing) file and folder icons using SHGetFileInfo in C#

The demo project is pretty self explanatory but basically you just have to do:

private System.Windows.Forms.ListView FileView;

private ImageList _SmallImageList = new ImageList();
private ImageList _LargeImageList = new ImageList();
private IconListManager _IconListManager;

in the constructor:

_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;

and then finally when you create the ListViewItem:

ListViewItem item = new ListViewItem(file.Name, _IconListManager.AddFileIcon(file.FullName));

Worked great for me.

oreon
+1  A: 

Edit: Here is a version without 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;
}
dummy
+5  A: 

You might find the use of Icon.ExtractAssociatedIcon a much simpler (an managed) approach than using SHGetFileInfo. But watch out: two files with the same extension may have different icons.

Martin Plante