Click here to Skip to main content
Licence CPOL
First Posted 12 Jan 2005
Views 111,371
Downloads 2,740
Bookmarked 109 times

IconHandler

By | 1 Feb 2006 | Article
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)

About the Author

Gil.Schmidt

Team Leader
EZFace
Israel Israel

Member

Web Team Leader

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralThanks PinmemberMuammar©0:26 6 Jul '09  
GeneralTransparency Pinmembercawoodm4:12 18 Jun '08  
AnswerRe: Transparency Pinmembercawoodm4:18 18 Jun '08  
GeneralRe: Transparency PinmemberMuammar©0:24 6 Jul '09  
Questionhow to get the associated icons in vc .net Pinmemberitbuff2:40 6 Nov '06  
how to get the associated icons in vc .net
QuestionSaving a 16x16 icon Pinmemberekittykat4918:53 17 Oct '06  
GeneralSource project won't build Pinmemberwaveangle15:23 12 Oct '06  
GeneralRe: Source project won't build Pinmemberekittykat4918:57 17 Oct '06  
Question48x48 icons? Pinmemberlpellerin6:57 26 Jan '06  
AnswerRe: 48x48 icons? PinmemberGil_Schmidt7:05 26 Jan '06  
GeneralRe: 48x48 icons? Pinmemberlpellerin7:21 26 Jan '06  
GeneralA bug fix PinmemberSickLab13:17 5 Jan '06  
GeneralRe: A bug fix PinmemberGil_Schmidt4:03 11 Jan '06  
GeneralRe: A bug fix Pinmemberhg0000006:18 31 Jan '06  
GeneralRe: A bug fix PinmemberGil_Schmidt7:09 31 Jan '06  
QuestionIcon by extension does not work on my machine PinmemberKenneth Broendum0:34 10 Nov '05  
AnswerRe: Icon by extension does not work on my machine PinmemberGil_Schmidt0:46 10 Nov '05  
GeneralRe: Icon by extension does not work on my machine PinmemberKenneth Broendum1:29 10 Nov '05  
GeneralRe: Icon by extension does not work on my machine PinmemberGil_Schmidt1:43 10 Nov '05  
GeneralRe: Icon by extension does not work on my machine PinmemberKenneth Broendum1:58 10 Nov '05  
GeneralRe: Icon by extension does not work on my machine PinmemberGil_Schmidt2:57 10 Nov '05  
GeneralRe: Icon by extension does not work on my machine PinmemberKenneth Broendum9:14 10 Nov '05  
GeneralRe: Icon by extension does not work on my machine PinmemberGil_Schmidt0:28 13 Jan '06  
GeneralDestroy Unmanaged Icons PinmemberDrGUI6:11 30 Oct '05  
GeneralRe: Destroy Unmanaged Icons PinmemberGil_Schmidt8:20 30 Oct '05  

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.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120529.1 | Last Updated 1 Feb 2006
Article Copyright 2005 by Gil.Schmidt
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid