Click here to Skip to main content
11,721,053 members (84,381 online)
Click here to Skip to main content

IconHandler

, 1 Feb 2006 CPOL 126.9K 3.4K 116
Rate this:
Please Sign up or sign in to vote.
An icon handling class for icon extraction from files and registry

Icon Handler at work :)

Introduction

IconHandler is a class for getting icons from files and the default associated icons by the extension of the file.

Background

It was originally writtin for a P2P project that never got out, called Kibutz. I decided to add the shell and resource functions becouse of a comment I got here. The const value has also been fixed (check IconSize).

Using the code

The class includes four simple-to-use functions:

  • IconFromFile(Filename,IconSize,Index)
    This will get a single icon from a file with the specific index. If no icon was found or if the index was outside of the bounds, null will be returned.
  • IconsFromFile(Filename,IconSize)
    This will return an Icon typed array of icons.
  • IconFromExtension(Extension,IconSize)
    This will return an icon associated with an extension -- if it exists -- by using Shell API; if not null will be returned.
  • IconFromResource(string ResourceName)
    This will return an icon from the assembly resource if it exists.
/*
/*
 * IconHandler - by Gil Schmidt
 * 
 * - Originaly was writtin for a p2p project called Kibutz.
 * - The IconFromExtension might give you some problems if it won't find an
 *   icon for it( try/catch should be used).
 *
 * [Updated]
 * 
 * - Added Shell function for getting file extension after getting some commet
 *   about it, check link below.
 *   (http://www.codeguru.com/Csharp/Csharp/cs_misc/icons/article.php/c4261/)
 * - IconFromResource was added for having all the common needed functions for 
 *   handling icons.
 * - Readed DestroyIcon and adding GetManagedIcon, after verifying it's needed 
 *   (thanks DrGui and Kenneth Broendum).
 * - Removed the IconFromExtension that pulled the icon from the registry 
 *   (IconFromExtensionShell is default now).
 * - Fixed IconCount mistake (if the number of icon in the file was 0 and the
 *   index that was selected was also 0 the ExtractIconEx still got to run and
 *   crashed (thanks SickLab).
 * - Fixed iIcon (it was changed from IntPtr to int. on x64 systems IntPtr is 
 *   8 bytes which caused the mistake to popup) parameter in SHFILEINFO struct 
 *   (Thanks Stefan Mayr).
 * 
 * contact me at: Gil_Smdt@Hotmail.com
 * 
*/

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Reflection;
using System.IO;

namespace IconHandler
{
    struct SHFILEINFO 
    {
        public IntPtr hIcon;        
        public int iIcon;        
        public uint dwAttributes;    
        [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 260 )]
        public string szDisplayName;
        [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 80 )]
        public string szTypeName;
    };

    public enum IconSize : uint
    {
        Large = 0x0,  //32x32
        Small = 0x1 //16x16        
    }

    //the function that will extract the icons from a file
    public class IconHandler
    {
        const uint SHGFI_ICON = 0x100;
        const uint SHGFI_USEFILEATTRIBUTES    = 0x10;

        [DllImport("Shell32", CharSet=CharSet.Auto)]
        internal extern static int ExtractIconEx (
            [MarshalAs(UnmanagedType.LPTStr)] 
            string lpszFile,                //size of the icon
            int nIconIndex,                 
                //index of the icon (in case we have more 
                //than 1 icon in the file
            IntPtr[] phIconLarge,           //32x32 icon
            IntPtr[] phIconSmall,           //16x16 icon
            int nIcons);                    //how many to get

        [DllImport("shell32.dll")]
        static extern IntPtr SHGetFileInfo(
            string pszPath,                //path
            uint dwFileAttributes,        //attributes
            ref SHFILEINFO psfi,        //struct pointer
            uint cbSizeFileInfo,        //size
            uint uFlags);    //flags

        //we need this function to release the unmanaged resource,
        //the unmanaged resource will be copies to a managed one and 
        //it will be returned.
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        extern static bool DestroyIcon(IntPtr handle);

        //will return an array of icons 
        public static Icon[] IconsFromFile(string Filename,IconSize Size)
        {
            int IconCount = ExtractIconEx(Filename,-1,null,null,0); 
                //checks how many icons.
            IntPtr[] IconPtr = new IntPtr[IconCount];
            Icon TempIcon;

            //extracts the icons by the size that was selected.
            if (Size == IconSize.Small)
                ExtractIconEx(Filename,0,null,IconPtr,IconCount);
            else
                ExtractIconEx(Filename,0,IconPtr,null,IconCount);

            Icon[] IconList = new Icon[IconCount];
            
            //gets the icons in a list.
            for (int i = 0; i < IconCount; i++)
            {
                TempIcon = (Icon) Icon.FromHandle(IconPtr[i]);
                IconList[i] = GetManagedIcon(ref TempIcon);
            }

            return IconList;
        }

        //extract one selected by index icon from a file.
        public static Icon IconFromFile(
            string Filename,IconSize Size,int Index)
        {
            int IconCount = ExtractIconEx(Filename,-1,null,null,0); 
                //checks how many icons.
            if (IconCount <= 0 || Index >= IconCount) return null; 
                // no icons were found.

            Icon TempIcon;
            IntPtr[] IconPtr = new IntPtr[1];

            //extracts the icon that we want in the selected size.
            if (Size == IconSize.Small)
                ExtractIconEx(Filename,Index,null,IconPtr,1);
            else
                ExtractIconEx(Filename,Index,IconPtr,null,1);

            TempIcon = Icon.FromHandle(IconPtr[0]);

            return GetManagedIcon(ref TempIcon);
        }
        public static Icon IconFromExtension(string Extension,IconSize Size)
        {
            try
            {
                Icon TempIcon;

                //add '.' if nessesry
                if (Extension[0] != '.') Extension = '.' + Extension;

                //temp struct for getting file shell info
                SHFILEINFO TempFileInfo = new SHFILEINFO();
                
                SHGetFileInfo(
                    Extension,
                    0, 
                    ref TempFileInfo,
                    (uint)Marshal.SizeOf(TempFileInfo),
                    SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | (uint) Size);

                TempIcon = (Icon) Icon.FromHandle(TempFileInfo.hIcon);
                return GetManagedIcon(ref TempIcon);
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(
                    "error while trying to get icon for " + Extension + 
                    " :" + e.Message);
                return null;
            }
        }

        /*
         * this is the built in funcion provided by .Net framework for getting 
         * a file icon, i thought it's worth mentioning.
         * 
        public static Icon IconFromExtension(string Filename)
        {
            return Icon.ExtractAssociatedIcon(Filename);
        }
        */

        public static Icon IconFromResource(string ResourceName)
        {
            Assembly TempAssembly = Assembly.GetCallingAssembly();

            return new Icon(TempAssembly.GetManifestResourceStream(
                ResourceName));
        }

        public static void SaveIconFromImage(
            Image SourceImage,string IconFilename,IconSize DestenationIconSize)
        {
            Size NewIconSize = DestenationIconSize == 
                IconSize.Large ? new Size(32,32) : new Size(16,16);

            Bitmap RawImage = new Bitmap(SourceImage,NewIconSize);
            Icon TempIcon = Icon.FromHandle(RawImage.GetHicon());
            FileStream NewIconStream = new FileStream(
                IconFilename,FileMode.Create);

            TempIcon.Save(NewIconStream);

            NewIconStream.Close();
        }

        public static void SaveIcon(Icon SourceIcon,string IconFilename)
        {
            FileStream NewIconStream = new FileStream(
                IconFilename,FileMode.Create);

            SourceIcon.Save(NewIconStream);

            NewIconStream.Close();                                       
        }

        public static Icon GetManagedIcon(ref Icon UnmanagedIcon)
        {
            Icon ManagedIcon = (Icon) UnmanagedIcon.Clone();

            DestroyIcon(UnmanagedIcon.Handle);

            return ManagedIcon;
        }
    }
}

/* EOF */

Points of interest

What got me to write this was that I didn't find anything like this around. It's not complicated code, but when you want to use icons you don't plan on wasting your time dealing with it a lot. So, it's comfortable to have this little piece of code around.

History

  • 12 January, 2005 - Original version posted
  • 1 February, 2006 - First update
  • 23 May, 2007 - Second update

License

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

Share

About the Author

Gil.Schmidt
Team Leader
Israel Israel
No Biography provided

You may also be interested in...

Comments and Discussions

 
GeneralThanks Pin
Muammar©6-Jul-09 0:26
memberMuammar©6-Jul-09 0:26 
GeneralTransparency Pin
cawoodm18-Jun-08 4:12
membercawoodm18-Jun-08 4:12 
AnswerRe: Transparency Pin
cawoodm18-Jun-08 4:18
membercawoodm18-Jun-08 4:18 
GeneralRe: Transparency Pin
Muammar©6-Jul-09 0:24
memberMuammar©6-Jul-09 0:24 
Questionhow to get the associated icons in vc .net Pin
itbuff6-Nov-06 2:40
memberitbuff6-Nov-06 2:40 
QuestionSaving a 16x16 icon Pin
ekittykat4917-Oct-06 18:53
memberekittykat4917-Oct-06 18:53 
GeneralSource project won't build Pin
waveangle12-Oct-06 15:23
memberwaveangle12-Oct-06 15:23 
GeneralRe: Source project won't build Pin
ekittykat4917-Oct-06 18:57
memberekittykat4917-Oct-06 18:57 
Question48x48 icons? Pin
lpellerin26-Jan-06 6:57
memberlpellerin26-Jan-06 6:57 
AnswerRe: 48x48 icons? Pin
Gil_Schmidt26-Jan-06 7:05
memberGil_Schmidt26-Jan-06 7:05 
GeneralRe: 48x48 icons? Pin
lpellerin26-Jan-06 7:21
memberlpellerin26-Jan-06 7:21 
GeneralA bug fix Pin
SickLab5-Jan-06 13:17
memberSickLab5-Jan-06 13:17 
GeneralRe: A bug fix Pin
Gil_Schmidt11-Jan-06 4:03
memberGil_Schmidt11-Jan-06 4:03 
GeneralRe: A bug fix Pin
hg00000031-Jan-06 6:18
memberhg00000031-Jan-06 6:18 
GeneralRe: A bug fix Pin
Gil_Schmidt31-Jan-06 7:09
memberGil_Schmidt31-Jan-06 7:09 
QuestionIcon by extension does not work on my machine Pin
Kenneth Broendum10-Nov-05 0:34
memberKenneth Broendum10-Nov-05 0:34 
AnswerRe: Icon by extension does not work on my machine Pin
Gil_Schmidt10-Nov-05 0:46
memberGil_Schmidt10-Nov-05 0:46 
GeneralRe: Icon by extension does not work on my machine Pin
Kenneth Broendum10-Nov-05 1:29
memberKenneth Broendum10-Nov-05 1:29 
GeneralRe: Icon by extension does not work on my machine Pin
Gil_Schmidt10-Nov-05 1:43
memberGil_Schmidt10-Nov-05 1:43 
GeneralRe: Icon by extension does not work on my machine Pin
Kenneth Broendum10-Nov-05 1:58
memberKenneth Broendum10-Nov-05 1:58 
GeneralRe: Icon by extension does not work on my machine Pin
Gil_Schmidt10-Nov-05 2:57
memberGil_Schmidt10-Nov-05 2:57 
GeneralRe: Icon by extension does not work on my machine Pin
Kenneth Broendum10-Nov-05 9:14
memberKenneth Broendum10-Nov-05 9:14 
GeneralRe: Icon by extension does not work on my machine Pin
Gil_Schmidt13-Jan-06 0:28
memberGil_Schmidt13-Jan-06 0:28 
GeneralDestroy Unmanaged Icons Pin
DrGUI30-Oct-05 6:11
memberDrGUI30-Oct-05 6:11 
GeneralRe: Destroy Unmanaged Icons Pin
Gil_Schmidt30-Oct-05 8:20
memberGil_Schmidt30-Oct-05 8:20 
GeneralRe: Destroy Unmanaged Icons Pin
The_Mega_ZZTer2-Nov-05 16:29
memberThe_Mega_ZZTer2-Nov-05 16:29 
GeneralRe: Destroy Unmanaged Icons Pin
Gil_Schmidt2-Nov-05 21:47
memberGil_Schmidt2-Nov-05 21:47 
GeneralRe: Destroy Unmanaged Icons Pin
taoufik13-Jan-06 0:11
membertaoufik13-Jan-06 0:11 
GeneralRe: Destroy Unmanaged Icons Pin
Patrick Sears9-Dec-06 6:28
memberPatrick Sears9-Dec-06 6:28 
QuestionHow could i.... Pin
tayspen8-Sep-05 15:11
membertayspen8-Sep-05 15:11 
AnswerRe: How could i.... Pin
Gil_Schmidt23-Sep-05 8:14
memberGil_Schmidt23-Sep-05 8:14 
AnswerRe: How could i.... Pin
Gil_Schmidt23-Sep-05 8:33
memberGil_Schmidt23-Sep-05 8:33 
GeneralRe: How could i.... Pin
tayspen23-Sep-05 8:36
membertayspen23-Sep-05 8:36 
GeneralDoes not work with some extensions Pin
click.ok14-May-05 10:54
memberclick.ok14-May-05 10:54 
GeneralRe: Does not work with some extensions Pin
Gil_Schmidt15-May-05 9:04
memberGil_Schmidt15-May-05 9:04 
GeneralRe: Does not work with some extensions Pin
click.ok16-May-05 3:56
memberclick.ok16-May-05 3:56 
GeneralCorrection 2 Pin
Darek Maciejewski8-Apr-05 8:59
memberDarek Maciejewski8-Apr-05 8:59 
GeneralRe: Correction 2 Pin
Gil_Schmidt8-Apr-05 9:02
memberGil_Schmidt8-Apr-05 9:02 
GeneralNice Job Pin
Charlie Williams14-Jan-05 5:06
memberCharlie Williams14-Jan-05 5:06 
GeneralRe: Nice Job Pin
Gil_Schmidt14-Jan-05 6:25
memberGil_Schmidt14-Jan-05 6:25 
GeneralCorrection Pin
David M. Kean12-Jan-05 18:43
memberDavid M. Kean12-Jan-05 18:43 
GeneralRe: Correction Pin
Gil_Schmidt16-Jan-05 5:33
memberGil_Schmidt16-Jan-05 5:33 

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 | Terms of Use | Mobile
Web02 | 2.8.150901.1 | Last Updated 1 Feb 2006
Article Copyright 2005 by Gil.Schmidt
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid