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