views:

802

answers:

4

Note: Question http://stackoverflow.com/questions/220465/using-256-x-256-vista-icon-in-application deals with using a "Vista" icon as the application's icon. This question deals with manually painting a Vista icon.

Note: Question http://stackoverflow.com/questions/281999/winforms-net-20-how-to-paint-with-the-proper-icon deals with painting a Vista icon loaded from a file. This question deals with painting a Vista icon that is loaded from a .resource.


i've included an icon in my Visual Studio project that has various formats:

  • 16x16
  • 32x32
  • 48x48
  • 256x256 (png compressed)

Now want to draw the 256x256 version. None of the following things i've tried work.

The following draws the 32x32 format stretched to 256x256:

Icon ico = Properties.Resources.TestIconThatHasA256PNGFormat;
e.Graphics.DrawIcon(ico, new Rectangle(0, 0, 256, 256));

The following draws the 32x32 format unstretched:

Icon ico = Properties.Resources.TestIconThatHasA256PNGFormat;
e.Graphics.DrawIconUnstretched(ico, new Rectangle(0, 0, 256, 256));

The following draws the 32x32 format stretched to 256x256:

Icon ico = Properties.Resources.TestIconThatHasA256PNGFormat;
e.Graphics.DrawImage(ico.ToBitmap(), new Rectangle(0, 0, 256, 256));

The following draws the 48x48 format stretched to 256x256:

Icon ico = Properties.Resources.TestIconThatHasA256PNGFormat;
e.Graphics.DrawIcon(
      new Icon(ico, new Size(256, 256)),     
      new Rectangle(0, 0, 256, 256));

How do i draw the 256x256 format icon?


Notes:

  1. The icon is not coming from a file, so PInvoking LoadImage() will not help.

  2. The icon is not the icon associated with a file, so PInvoking SHGetFileInfo() will not help. Nor will using Icon.ExtractAssociatedIcon.

  3. i'm also not trying to author icons with a 256x256 format at runtime, so libraries designed to do that will not help.

    [2]: Question http://stackoverflow.com/questions/281999/winforms-net-20-how-to-paint-with-the-proper-icon

A: 

I asked a similar question a while ago but with not much luck. Some of the answers in my post may help you, there was one way but it looks pretty hard. Link to my post here

Nathan W
Answers there are used to extract the associated icon for a file; which would only give you a vista icon if you were on vista. It also requires that you're getting the icon from a file. This is an icon i've authored.
Ian Boyd
+1  A: 

I answered the same question here...

Hans Passant
Oddly enough that is my question you answered over there. But that doesn't answer this question. That answer is used to load an icon from a file. This question doesn't have a file.
Ian Boyd
There's no API to load these kind of icons from a stream. The old COM interfaces .NET uses weren't updated in Vista.
Hans Passant
Could you include these COM interface classes and interface IID's? i'd be curious see the COM objects that .NET is using to load and paint icons.
Ian Boyd
There is the IExtractIcon interface: http://msdn.microsoft.com/en-us/library/bb761854(VS.85).aspx - and the documentation also hints at the http://msdn.microsoft.com/en-us/library/bb776417(VS.85).aspx ExtractIcon API call. None of these seem to be any good for 256x256 icons though.
romkyns
+3  A: 

The ResourceManager loads the icon based on the bits stored in the resources. However, the way it handles loading won't let you access the 256x256 icon (this information does not make its way into the System.Drawing.Icon that you are getting back).

I am sorry to disappoint you, but the only way which works that I am aware of is to load the icon through a P/Invoke of LoadImage and working with a file (yes, I know, that's not what you were looking for). So the new question should be: how do I extract the bits of a given resource so that I can store them to a file? I fear that this isn't possible either, having done some stepping through System.Resources.ResourceReader, as the resource data seems to be a collection of serialized .NET objects.

Anyway, for those who can afford to load the icon from a .ICO file (and for myself, as a future reference on how to load 256x256 icons), call IconConverter.LoadIcon:

using System.Runtime.InteropServices;

static class IconConverter
{
    public static System.Drawing.Icon LoadIcon(string path, int width, int height)
    {
        System.IntPtr hIcon;
        hIcon = LoadImage (System.IntPtr.Zero, path, IMAGE_ICON, width, height,
                           LR_LOADFROMFILE);
        if (hIcon == System.IntPtr.Zero)
        {
            return null;
        }
        return System.Drawing.Icon.FromHandle (hIcon);
    }

    const int IMAGE_ICON = 1;
    const int LR_LOADFROMFILE = 0x0010;

    [DllImport ("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    static extern System.IntPtr LoadImage(System.IntPtr hInstance,
                                          string lpszName, uint uType,
                                          int cxDesired, int cyDesired,
                                          uint fuLoad);
}

Once you have the System.Drawing.Icon in the expected size, just paint it using graphics.DrawIconUnstretched.

Pierre
A: 

Today, I made a very nice function for extracting the 256x256 Bitmaps from Vista icons.

I use it to display the large icon as a Bitmap in "About" box.

This function takes Icon object as a parameter. So, you can use it with any icons - from resources, from files, from streams, and so on. It runs on any OS, because it does not use any Win32 API, it is 100% managed code :-)

Bitmap ExtractVistaIcon(Icon icoIcon)

I posted my function here: ExtractVistaIcon()

SLA80