Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Associated Icons Image Control

0.00/5 (No votes)
1 Jun 2005 1  
A web control that displays the icon image currently associated with a given file or file extension.

Introduction

This custom server control displays the icon that is currently associated with the given file extension. The file icon associations are kept by the operating system and can be retrieved with a single Win32 API call.

Use this control when you just need to display a well known file icon or even when you want to show any list of files with their appropriate icons.

Using the code

The article download contains a VS.NET 2003 project of a sample ASP.NET application. This application contains the two files that hold the important part of the code. These files are AssociatedIcon.cs and IconExtractor.cs.

Instead of just extracting the whole project from the zipped file, I'd like to suggest that you use your own installation of Visual Studio .NET to create a new C# ASP.NET project named AssociatedIcons. Add two folders to your application, Controls and IconStubs. Delete the default Webform1.aspx file and add a new WebForm named TestPage.

To save some major typing time, just get the file IconExtractor.cs and put it in the Controls folder of your project. Add a new class named AssociatedIcon in the same Controls folder. This class will be our custom control.

After all that, your project should be looking like the image below:

Add the following code to the AssociatedIcon.cs file that you just created:

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace AssociatedIcons.Controls
{
    [ToolboxData("<{0}:AssociatedIcon 
        runat="server"></{0}:AssociatedIcon>")]
    public class AssociatedIcon : Image
    {
        /*****
         * This control accepts a file name or file extension,
         * determines the associated icon, and displays it on the page
         * ***/

        /// <summary>

        /// Gets or sets a file name or extension (including the dot)

        /// to display the associated icon

        /// </summary>

        public string ExtensionOrFile
        {
            get
            {
                string s = (string)ViewState["ExtensionOrFile"];
                if(s == null) return "";
                return s;
            } 
            set{ ViewState["ExtensionOrFile"] = value; } 
        }

        /// <summary>

        /// Determines if the icon size will be 16x16 or 32x32 pixels

        /// </summary>

        public bool LargeIcon
        {
            get
            {
                object obj = ViewState["LargeIcon"];
                if(obj == null) return false;
                return (bool)obj;
            } 
            set
            {
                ViewState["LargeIcon"] = value;
            }
        }

        public override string ImageUrl
        {
            get{ return base.ImageUrl;}
            set{ throw new 
                 InvalidOperationException("The ImageUrl cannot be set.");}
        }

        protected override void OnLoad(EventArgs e)
        {
            if(!Page.IsPostBack)
                base.ImageUrl = 
                  IconExtractor.GetUrlToIcon(ExtensionOrFile, LargeIcon);
        }

    }
}

Because we will be writing files in the IconStubs folder, you'll need to give write permission to the ASPNET user in that folder. In case you have never done this before, the process is simple. In any Windows Explorer window, find the IconStubs folder, right-click it and select Properties. Go to the Security tab. If the Allow inherited permissions[...] checkbox is checked, uncheck it. Use the Add button to add the ASPNET user to the list (in case it's not already there). With the ASPNET user in the list, select it and choose only the Allow Write checkbox in the permissions list. See the image below. After that, click OK and you're done.

How this control works

As you can see from the code above, our control is a fairly a simple extension of the System.Web.UI.WebControls.Image server control. We added a property to hold the desired file extension (or file name) and another one to specify if the desired icon will be the small (16 x 16 pixels) or the large (32 x 32 pixels) version. We also inhibit the setting of the ImageUrl property directly so that nobody changes it inadvertently.

As you can also notice, there's not much going on in this control's code. The real meat of the process is implemented by the IconExtractor class.

The IconExtractor class

The central piece of the icon extraction process is a call to the SHGetFileInfo Shell32 Windows API. This API, among other things, give us a handle to the associated icon (small or large) for the given file. After that, the code will save the icon as a PNG image with a transparent background in the IconStubs folder. Next time the same extension icon is requested, the URL to the already existing image file will be returned, without any new file creation. After a while, you should get your IconStubs folder full of the images for all the icons you used, as shown below:

Note: IE (at least the version I have: 6.0.2800.1106) has a flaw in transparent PNG rendering, causing the transparent areas to render gray. The code includes comments that help you change the implementation from PNG to GIF, losing the transparent background.

Note: The implementation of transparent background in GIF images is way too complicated in .NET, involving unsafe blocks of code, so I decided not to include it in this sample, for the sake of simplicity (or laziness, if you'd like me to be really honest :) ).

Test driving the control

To see how the control works, let's put some content in our TestPage.aspx. First, let's register a tag prefix with our Controls namespace. Add the following to the top of you page's ASPX:

<%@ Register Tagprefix="SP" 
    Namespace="AssociatedIcons.Controls" Assembly="AssociatedIcons" %>

Now let's add some instances of our control in the page, like this:

        <form id="TestPage" method="post" runat="server">
            <br>
            <SP:AssociatedIcon id="file1" runat="server" 
                ExtensionOrFile=".doc" largeIcon="True" />
            MyDocument.doc

            <br>
            <SP:AssociatedIcon id="file2" runat="server" 
                ExtensionOrFile="file.bmp" largeIcon="false" />
            MyIcon.bmp

            <br>
            <SP:AssociatedIcon id="Associatedicon1" runat="server" 
                ExtensionOrFile="file.jpg" largeIcon="true" />
            MyIcon.jpg

            <br>
            <SP:AssociatedIcon id="Associatedicon2" runat="server" 
                ExtensionOrFile="file.gif" largeIcon="false" />
            MyIcon.gif

            <br>
            <SP:AssociatedIcon id="Associatedicon3" runat="server" 
                ExtensionOrFile="file.mp3" largeIcon="true" />
            MyIcon.mp3

            <br>
            <asp:Button ID=test Runat="server"  Text=test />
        </form>

When you save, compile, and run this page, you should see something similar to the image below. The icons may vary depending on which programs you have associated with the file extensions.

Enhancement suggestions

Like any sample, the code in this article is far from ideal and full of opportunities for new or enhanced features (maybe a few bugs here and there too). Some of the ideas that come to mind as enhancements to this code are:

  • Using a configuration value to determine both the physical and virtual paths of the icon image files. That way you can potentially use this control in more than one application and share the same set of icons, from the same folder.
  • Implementing the background transparency in GIF. Change the code to produce GIFs instead of PNGs (while IE does not get the transparent PNG bug fixed) and make the background color transparent. Here are two nice references that can help you with that: Transparent background using GDI+ by Eric Johnson (newsgroups post) and Bob Powell's GDI+ FAQ.

References

  • PInvoke.net - I can't get around using the Win32 API without the help of this awesome Wiki and the nice people that contribute to it.
  • Bob Powell's GDI+ FAQ on GIF transparency.
  • Transparent background using GDI+ by Eric Johnson. If the link stops working, just search for the title in the microsoft.public.dotnet.framework.drawing newsgroup.

History

  • May 29th 2005 - Code submitted.

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