Click here to Skip to main content
15,886,066 members
Articles / Web Development / ASP.NET

Associated Icons Image Control

Rate me:
Please Sign up or sign in to vote.
3.92/5 (9 votes)
1 Jun 20055 min read 110.4K   866   34  
A web control that displays the icon image currently associated with a given file or file extension.
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Runtime.InteropServices;

namespace AssociatedIcons.Controls
{
	public sealed class IconExtractor
	{
		private IconExtractor()
		{
		}

		internal static string GetUrlToIcon(string extensionOrFile, bool large)
		{
			//let's extract the extension from the given argument
			string extension = GetExtension(extensionOrFile);
			string url = GetIconVirtualPath(extension, large);
			return ((Page)HttpContext.Current.Handler).ResolveUrl(url);
		}

		private static string GetIconVirtualPath(string extension, bool large)
		{
			string fileName = string.Format("ext.{0}{1}.png", large?"32":"16", extension);

			//--if you decide to use GIF, use the following line instead
			//string fileName = string.Format("ext.{0}{1}.gif", large?"32":"16", extension);

			string path = Path.Combine(GetStubFilesPhysicalFolder(), fileName);

			//we will ensure the image file with the icon exists
			if(!File.Exists(path))
			{
				//the icon file has not been created yet. Let's do it
				using(Icon icon = ExtractIconForExtension(extension, large))
				using(Bitmap bmp = icon.ToBitmap())
				using(Graphics g = Graphics.FromImage(bmp))
				{
					//we will paint the backgound in HotPink (praying that
					// nobody in their rightful mind would use this color 
					// in their icons) and make it the transparent color
					bmp.MakeTransparent(Color.HotPink);
					g.Clear(Color.HotPink);

					//--alternatively you can choose to paint it in a regular
					//-- color, like plain white, and forget transparency altogether.
					//--  you cand do that by replacing those two lines
					//--  above with the following one
					//g.Clear(Color.White);

					//Paint the icon
					g.DrawIcon(icon, new Rectangle(0, 0, icon.Width, icon.Height));
					
					//save the image in a PNG file
					bmp.Save(path, ImageFormat.Png);

					//--save the image in a GIF file
					//---- if you decide to save as GIF, use the following line instead
					//bmp.Save(path, ImageFormat.Gif);
				}
			}

			string vpath = Path.Combine(GetStubFilesVirtualFolder(), fileName);
			return vpath;
		}

		#region Icon Extraction Code


		private static Icon ExtractIconForExtension(string extension, bool large)
		{
			if(extension != null)
			{
				//let's just make up a file name with that extension
				string fictitiousFile = "0" + extension; 
				//now get the icon for that file
				return GetAssociatedIcon(fictitiousFile, large);
			}
			else
			{
				throw new ArgumentException("Invalid file or extension.", "fileOrExtension");
			}

		}

		private static string GetExtension(string extensionOrFile)
		{
			try
			{
				string ext = System.IO.Path.GetExtension(extensionOrFile);
				ext = ext.Replace("#", "_");
				ext = ext.Replace("&", "_");
				return ext;
			}
			catch{/**/}

			return "";
		}

		private static string GetStubFilesVirtualFolder()
		{
			//TODO: You should make this folder path
			//  be derived of a config value
			//  instead of just hardcoding like in 
			//  the following line
			return "~/IconStubs";
		}

		private static string GetStubFilesPhysicalFolder()
		{
			//TODO: You should make this folder path
			//  be derived of a config value
			//  instead of just hardcoding like in 
			//  the following line
			return HttpContext.Current.Server.MapPath(GetStubFilesVirtualFolder());
		}


		private static Icon GetAssociatedIcon(string stubPath, bool large)
		{
			SHFILEINFO info = new SHFILEINFO(true);
			int cbFileInfo = Marshal.SizeOf(info);
			SHGFI flags;

			if (large)
				flags = SHGFI.Icon|SHGFI.LargeIcon|SHGFI.UseFileAttributes;
			else
				flags = SHGFI.Icon|SHGFI.SmallIcon|SHGFI.UseFileAttributes;

			
			SHGetFileInfo(stubPath, 256, out info,(uint)cbFileInfo, flags);
			return (Icon)Icon.FromHandle(info.hIcon);
		}

		



		#endregion

		#region Win32 API imports 



		[DllImport("shell32.dll", CharSet=CharSet.Auto)]
		private static extern int  SHGetFileInfo(
			string pszPath     ,
			int    dwFileAttributes,
			out    SHFILEINFO psfi ,
			uint   cbfileInfo      ,
			SHGFI  uFlags );

		private const int MAX_PATH = 260;
		private const int MAX_TYPE = 80 ;

		private struct SHFILEINFO
		{
			public SHFILEINFO(bool b)
			{
				hIcon=IntPtr.Zero;
				iIcon=0;
				dwAttributes=0;
				szDisplayName="";
				szTypeName="";
			}


			public IntPtr hIcon;
			public int iIcon;
			public uint dwAttributes;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)]
			public string szDisplayName;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_TYPE)]
			public string szTypeName;
		};

		[Flags]
			enum SHGFI : int
		{
			/// <summary>get icon</summary>
			Icon         = 0x000000100,   

			/// <summary>get display name</summary>
			DisplayName      = 0x000000200, 

			/// <summary>get type name</summary>
			TypeName     = 0x000000400, 

			/// <summary>get attributes</summary>
			Attributes       = 0x000000800, 

			/// <summary>get icon location</summary>
			IconLocation     = 0x000001000, 
 
			/// <summary>return exe type</summary>
			ExeType      = 0x000002000,  

			/// <summary>get system icon index</summary>
			SysIconIndex     = 0x000004000,  

			/// <summary>put a link overlay on icon</summary>
			LinkOverlay      = 0x000008000,  

			/// <summary>show icon in selected state</summary>
			Selected     = 0x000010000,  

			/// <summary>get only specified attributes</summary>
			Attr_Specified   = 0x000020000, 
 
			/// <summary>get large icon</summary>
			LargeIcon    = 0x000000000,  

			/// <summary>get small icon</summary>
			SmallIcon    = 0x000000001,  

			/// <summary>get open icon</summary>
			OpenIcon     = 0x000000002,  

			/// <summary>get shell size icon</summary>
			ShellIconize     = 0x000000004,  

			/// <summary>pszPath is a pidl</summary>
			PIDL         = 0x000000008,  

			/// <summary>use passed dwFileAttribute</summary>
			UseFileAttributes= 0x000000010,  

			/// <summary>apply the appropriate overlays</summary>
			AddOverlays      = 0x000000020,  

			/// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary>
			OverlayIndex     = 0x000000040,  
		}   

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
Sergio Pereira is a senior software developer and architect. He currently makes his services available throughout Chicago and suburbs. Sergio has always made himself proficient in mainstream Microsoft technologies and has a deep interest in emerging technologies and the software life cycle aspect of development.
Feel free to contact Sergio at sergio_pereira(AT)msn(dot)com.

Comments and Discussions