Click here to Skip to main content
Click here to Skip to main content
Go to top

OSIcon

, 12 Jan 2010
Rate this:
Please Sign up or sign in to vote.
Library for handling and retrieving system icons.

OSIcon_Explorer-MyComputer.png

OSIcon_Explorer.png

OSIcon_Associations.png

OSIcon_WindowsThumbnails.png

OSIcon_IconExplorer.png

Table of Contents

Introduction

This library can retrieve icons from extensions and files, with additional information like file type (hard drive, folder, PHP Script File, ...). The library also provides a class for CACHE icons and creates an ImageList with the added icons.

Using the code

Classes in the library

  • WinAPI namespace (Contains all Win API calls)
    • Shell32 static class (all API calls for Shell32.dll)
    • Shell32Vista static class (all API calls for Shell32.dll)
    • User32 static class (all API calls for User32.dll)
    • Comctl32 static class (all API calls for Comctl32.dll)
    • Kernel32 static class (all API calls for Kernel32.dll)
    • IEnumIDList interface
    • IShellFolder interface
  • Utils static class (helper functions)
  • IconReader static class (read, handle icons)
  • IconManager class (IconReader wrapper with caching features, automatic creation of ImageList)
  • About static class (stores some constants about the library, author, webpage, etc...)

Using the IconReader class

Get any icon from a file using "OSIcon.IconReader.ExtractIconFromFile(path, isLarge);".

// To extract the file icon we simply can do:
// First param will be the path to file.
// Last param define icon size (true = Large, false = Small)
Icon icon = OSIcon.IconReader.ExtractIconFromFile("C:\\pathtofile.png", true);

Now, if you want to extract an icon from a resource file like shell32.dll, you can do: "OSIcon.IconReader.ExtractIconFromFile(path, iconIndex);".

// 5, is the icon index
// http://cfs6.tistory.com/upload_control/download.blog?
// fhandle=YmxvZzEwMTUzNkBmczYudGlzdG9yeS5jb206L2F0dGFjaC8wLzAxMDAwMDAwMDAwMC5qcGc%3D
// 5 will return Open Folder image from shell32.dll
Icon icon = OSIcon.IconReader.ExtractIconFromFile("C:\\Windows\\system32\\shell32.dll", 5);

In Windows Explorer, FileZilla, etc., we can see the file type (Folder, PHP Script, Dynamic Link Library, etc.). To retrieve that information, we need to use some API calls. Using OSIcon, this is quite simple: "OSIcon.IconReader.GetFileIcon(pathOrExtension, IconReader.IconSize, Shell32.SHFILEINFO);".

// NOTE: filename can be an partial extension (.png), or a full path ("C:\\file.png")
// shfi, store some file information
OSIcon.WinAPI.Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
Icon icon = OSIcon.IconReader.GetFileIcon(".png", IconReader.IconSize.Large, false, ref shfi);
MessageBox.Show(string.Format("Display Name: {0}\nFile Type: {1}", 
                shfi.szDisplayName, shfi.szTypeName));

We can also retrieve file extensions from regedit and extract their icons, using: "OSIcon.IconReader.GetFileTypeAndIcon();".

// Get all available extensions
// Dictionary Key = extension, value = path to icon
Dictionary<string, string> _iconList = _iconList = 
OSIcon.IconReader.GetFileTypeAndIcon();
// Foreach each extension
foreach (KeyValuePair<string, string> list in _iconList)
// Extract icon from file
Icon icon = OSIcon.IconReader.ExtractIconFromFile(_iconList[extension], 
                              isLarge ? true : false);

Getting all icons on a file is quite simple, using: "ExtractIconsFromFile(path, isLarge);".

// From Sample Application see: "IconExplorer.cs" UserControl
filename = "C:\\Windows\\system32\\shell.dll";
Icon[] icons = IconReader.ExtractIconsFromFile(filename, true);
if(icons.Length == 0) return; // No icons found, return
// Loop through icons array
for (int i = 0; i < icons.Length; i++)
{
    // Do something here, im adding icon to an ImageList
    imageList.Images.Add(i.ToString(), icons[i]);
}

Using the IconManager class

Sometimes we need to display our files and have 100s of files of the same type, e.g., .php; you can reuse icons obtained from the first PHP file in that case.

  • IconProperties class
    • IconsInfo (stores icons information) Dictionary<IconReader.IconSize, Shell32.SHFILEINFO>
    • IconsIndex (icons index from ImageList) Dictionary<IconReader.IconSize, int>
    • Icons (stores icons image) Dictionary<IconReader.IconSize, Icon>
// If you want create a ImageList to store collected icons use true
// Small ImageList (true/false), Large ImageList (true/false)
// new OSIcon.IconManager() == new OSIcon.IconManager(true, true)
//
// Initalize Class, and create small, large, extralarge, jumbo
// Last param if set true, disable ExtraLarge or Jumbo if not supported by current OS
OSIcon.IconManager iconManager = new OSIcon.IconManager(true, true, true, true, true);
// Add some special icons to be used
// Add folder images
iconManager.AddFolder(iconManager.IconSizeAllSupported); 
// Add Computer Drives (DVD Drive, Floppy, Hard Disk, etc.)
iconManager.AddComputerDrives(iconManager.IconSizeAllSupported); 
 
// You also can add manualy, icons images to ImageList
// I use ":" because file path can't have ':' in name, so its a special mark
iconManager.IImageList[IconReader.IconSize.Small].Images.Add(
  ":Up-icon:", Properties.Resources.Up_icon16x16);
iconManager.IImageList[IconReader.IconSize.Large].Images.Add(
  ":Up-icon:", Properties.Resources.Up_icon32x32);
// ExtraLarge was instroduced on XP so if you running XP
// or above add ExtraLarge capabilities
if (OSIcon.Utils.IsXpOrAbove())
{
    iconManager.IImageList[IconReader.IconSize.ExtraLarge].Images.Add(
                ":Up-icon:", Properties.Resources.Up_icon48x48);
}
// Jumbo was instroduced on Vista so if you
// running Vista or above add Jumbo capabilities
if (OSIcon.Utils.IsVistaOrAbove())
{
    iconManager.IImageList[IconReader.IconSize.Jumbo].Images.Add(
          ":Up-icon:", Properties.Resources.Up_icon256x256);
}
// NOTE: iconManager.IImageList[IconReader.Size]
// can be assign in any control that uses ImageList

The class is initialized and ready to use; now, we create a function to show My Computer and the path contents:

void ShowMyComputer()
{
    // List all drives on computer
    foreach (string drive in Directory.GetLogicalDrives())
    {
        // Always when you add a icon to list it will return IconProperties 
        // and cache it on class
        OSIcon.IconManager.IconProperties iconProp = 
          OSIcon.iconManager.AddEx(drive, IconManager.IconSizeBoth);
        // Do something here!, sample from OSIcon Explorer:
        ListViewItem item = new ListViewItem(
          iconProp.IconsInfo[IconReader.IconSize.Small].szDisplayName);
        item.ImageIndex = iconProp.IconsIndex[IconReader.IconSize.Small];
        item.SubItems.Add(""); // Size
        item.SubItems.Add(iconProp.IconsInfo.Small.szTypeName); // Type name
        item.Tag = drive;
    }
}
 
// Next function will show path contents
public void ShowPathContents(string path)
{
    if (path == null) return;
    // If path is empty show my computer instead
    if (path == "") 
    {
        ShowMyComputer();
        return;
    }
    try
    {
        Cursor = Cursors.WaitCursor;
        string[] folders = Directory.GetDirectories(path);
        string[] files = Directory.GetFiles(path);
        foreach (string folder in folders) // get all folders on a path
        {
            DirectoryInfo dirInfo = new DirectoryInfo(folder);
            // Your Code go here!, sample from OSIcon Explorer
            ListViewItem item = new ListViewItem(Path.GetFileName(folder));
            item.Tag = folder;
            // Its a folder and its already added when we initalized the class, 
            // so we can directly get by:
            // Note: Make use of OSIcon.IconManager.FolderOpen and 
            // OSIcon.IconManager.FolderClosed constants
            IconManager.IconProperties iconProp = 
                iconManager.IconList[OSIcon.IconManager.FolderClosed];
            // we assign ImageList icon index to Image, you can use image 
            // key instead
            item.ImageIndex = iconProp.IconsIndex[IconReader.IconSize.Small];
            item.SubItems.Add("");
            item.SubItems.Add(iconProp.IconsInfo[IconReader.IconSize.Small].szTypeName);
            item.SubItems.Add(dirInfo.LastWriteTime.ToString());
            fileExplorerList.Items.Add(item);
        }
        foreach (string file in files)
        {
            FileInfo fi = new FileInfo(file);
            // Your Code go here!, sample from OSIcon Explorer
            // Now its a file, and we need try add the icon to class, if that 
            // icon already exist on class, will return the icon previous added
            // otherwise add and return.
            // I perfer use by extension because its easier to cache, because
            // 100 times .php is not the same as 100 times diferentFileNames.php
            IconManager.IconProperties iconProp = iconManager.AddEx(fi.Extension, 
                                                  IconManager.IconSizeAllSupported);
            ListViewItem item = new ListViewItem(fi.Name);
            item.Tag = fi.FullName;
            item.ImageIndex = iconProp.IconsIndex[IconReader.IconSize.Small];
            item.SubItems.Add(fi.Length.ToString());
            item.SubItems.Add(iconProp.IconsInfo[IconReader.IconSize.Small].szTypeName);
            item.SubItems.Add(fi.LastWriteTime.ToString());
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(string.Format("Error on trying acess: {0}\n\n{1}", 
                                      path, ex.Message), 
                                      "Error", 
                                      MessageBoxButtons.OK, 
                                      MessageBoxIcon.Error);
    }
    finally
    {
        Cursor = Cursors.Default;
    }
}

ListView only has an "ImageList" (should be 16 x 16px) and "LargeImageList". If you want to show "ExtraLarge" icons introduced in XP, and "Jumbo" from Vista or above, you have to change "LargeImageList" to the desired size, like:

/* 
* "fileExplorerList" is our ListView
* View:
* 0 = LargeIcons
* 1 = Details
* 2 = Small Icons
* 3 = List
* 4 = Title
* End View Enumeration
* 5 = ExtraLarge
* 6 = Jumbo
*/

private void ChangeListViewV(uint index)
{
    // If view is bigger than 4 means user wants ExtraLarge or Jumbo
    // To show that sizes View must be set to: View.LargeIcon
    // Also we have to change Large ImageList to the disired one
    if (index > 4)
    {
        // we change ImageList because ListView only have ImageList and LargeImageList
        switch (index)
        {
           case 5:
              fileExplorerList.LargeImageList = 
                    iconManager.IImageList[IconReader.IconSize.ExtraLarge];
              break;
           case 6:
              fileExplorerList.LargeImageList = 
                    iconManager.IImageList[IconReader.IconSize.Jumbo];
              break;
        }
        fileExplorerList.View = View.LargeIcon;
        return;
     }
     // View is under normal (small or large)
     // Get back to normal
     fileExplorerList.LargeImageList = iconManager.IImageList[IconReader.IconSize.Large];
     fileExplorerList.View = (View)index;
}

How can you get rid of of the added icons? It can be done like so:

// I dont need .txt icon anymore, and i will not use it from ImageList
iconManager.Remove(".txt", true);
// I dont need .wav icon anymore, but i still use it from ImageList
iconManager.Remove(".wav", false);
// IconSize Small is to small and Jumbo is too big for what i want
iconManager.Remove(".exe", IconReader.IconSize.Small | 
                                     IconReader.IconSize.Jumbo, true);

You need not hard-code with the IconManager class. Here is an example:

string name = ".dll";

// Bad Way:
IconProperties iconProp = iconManager.IconList[name];
if(!iconProp.IsValid(name, IconReader.IconSize.Small))
{
    OSIcon.WinAPI.Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
    iconManager.AddEx(name, IconReader.IconSize.Small, ref shfi);
}
if(!iconProp.IsValid(name, IconReader.IconSize.Jumbo))
{
    OSIcon.WinAPI.Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
    iconManager.AddEx(name, IconReader.IconSize.Jumbo, ref shfi);
}

// Good Way:
OSIcon.WinAPI.Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
IconProperties iconProp = iconManager.AddEx(name, 
     IconReader.IconSize.Small | IconReader.IconSize.Jumbo, ref shfi);

History

V2.0

  • Added About class
  • Added better commentaries
  • Added more samples
  • Updated sample application to use new icon sizes
  • Updated sample application to use the new library
IconProperties class
  • Added the "Remove" function, to remove an icon from a specified size
    • Supports multi sizes flags (IconReader.IconSize.Small | IconReader.IconSize.Large)
    • Returns a Dictionary<IconReader.IconSize, int> with removed icons, where int is the icon index on the ImageList
  • Added three "IsValid" functions
    • bool IsValidEx(IconReader.IconSize size), same as "IsValid(IconReader.IconSize size)", but also checks if the icon is not NULL
    • bool IsValid(), checks if that instance contains an icon
    • bool IsValid(IconReader.IconSize size), checks if an icon of a specified size exists in that instance
  • Changed "IconsInfo" type from struct to Dictionary<IconReader.IconSize, Shell32.SHFILEINFO>
  • Changed "IconsIndex" type from struct to Dictionary<IconReader.IconSize, int>
  • Changed "Icons" type from struct to Dictionary<IconReader.IconSize, Icon>
  • Implemented a "Tag" object
  • Disposable class
  • "IconProperties" is now a class, was a struct before
IconManager class
  • Fixed the "AddEx" function to allow adding more icons of different sizes
  • Added commentaries
  • Added two "Remove" functions, allows removing icons from the cache and from the ImageList
    • bool Remove(string path, bool removeIconFromList), removes all icons
    • bool Remove(string path, IconReader.IconSize iconSize, bool removeIconFromList), removes icons of a specified size only
  • Added private "Add" function, common actions when adding icons to list (to remove redundancy)
  • Added "IsValidEx" function, same as "IsValid", but returns the matched "IconProperties"; otherwise returns a new instance
  • Added two new constructors
    • public IconManager(bool createSmallIconList, bool createLargeIconList, bool createExtraLargeIconList, bool createJumboIconList)
    • public IconManager(bool createSmallIconList, bool createLargeIconList, bool createExtraLargeIconList, bool createJumboIconList, bool optimizeToOS)
  • Replaced "ImageListSmall" and "ImageListLarge" ImageLists with "IImageList" Dictionary<IconReader.IconSize, ImageList>
  • Added "IconSizeAllSupported" readeonly variable, contains all icon sizes supported by the current OS
  • Added "IconManager.IconSizeAll" constant, contains all icon sizes (Small | Large | ExtraLarge | Jumbo)
IconReader class
  • Changed all functions that contain a "IconReader.IconSize" to support new icon sizes (ExtraLarge, Jumbo)
  • Added the "ExtractIconFromResource" function, extracts an icon by name from the assembly
  • Added the "ExtractIconsFromFile" function, extracts all icons from a file; returns "Icon[]"
  • Added the "ExtractIconFromFileEx" function, identical to ExtractIconFromFile, but supports bigger sizes and icon information
  • Added two new icon sizes to "IconReader.IconSize"
    • IconReader.Iconsize.ExtraLarge (48x48 px.), XP or above supported
    • IconReader.Iconsize.Jumbo (256x256 px.), Vista or above supported
  • Renamed function "ExtractIcon" to "ExtractIconFromFile"
About class
  • Added the "ProjectAuthor" constant, my name
  • Added the "ProjecWWW" constant, this page URL

V1.0.01

  • Modified to correct egregious formatting and spelling errors - JSOP - 01/03/2010

V1.0

  • First release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 PinmemberAruny Yadav25-Jul-12 3:33 
QuestionGreat Article! PinmemberVB Rocks21-Jun-12 7:35 
AnswerRe: Great Article! Pinmemberknive121-Jun-12 15:44 
BugFolder icons always same PinmemberXmen W.K.18-May-12 6:19 
GeneralRe: Folder icons always same Pinmemberknive118-May-12 11:55 
GeneralRe: Folder icons always same PinmemberXmen W.K.18-May-12 14:41 
QuestionMy Computer icon PinmemberXmen W.K.15-May-12 0:46 
AnswerRe: My Computer icon Pinmemberknive118-May-12 4:16 
Questionpdf icon PinmemberDerek Hart13-Feb-12 17:55 
QuestionJumbo question [modified] Pinmemberchi70111120-Nov-11 17:01 
AnswerRe: Jumbo question Pinmemberknive121-Nov-11 5:20 
GeneralRe: Jumbo question Pinmemberchi70111121-Nov-11 16:17 
GeneralRe: Jumbo question Pinmemberknive121-Nov-11 16:32 
GeneralRe: Jumbo question Pinmemberchi70111121-Nov-11 17:20 
GeneralRe: Jumbo question Pinmemberknive121-Nov-11 17:24 
GeneralRe: Jumbo question Pinmemberchi70111121-Nov-11 19:47 
GeneralRe: Jumbo question Pinmemberknive122-Nov-11 5:07 
GeneralVery nice! PinmemberMember 81592677-Sep-11 1:58 
GeneralMy vote of 5 PinmemberAlex Essilfie2-Mar-11 1:51 
GeneralJust Awesome Pinmemberhighboy21-Nov-10 5:17 
GeneralRe: Just Awesome Pinmemberknive121-Nov-10 13:37 
QuestionLoaded in 764,6485 ms? PinmemberDarrenShultz4-Jan-10 12:44 
AnswerRe: Loaded in 764,6485 ms? Pinmemberknive14-Jan-10 13:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 12 Jan 2010
Article Copyright 2010 by Tiago Conceição
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid