views:

86

answers:

3

In particular I'd like to be able to get the small (16 x 16) icons at runtime.

I tried this:

new Icon(SystemIcons.Error, SystemInformation.SmallIconSize)

Which supposedly "attempts to find a version of the icon that matches the requested size", but it's still giving me a 32 x 32 icon. I also tried:

Size iconSize = SystemInformation.SmallIconSize;
Bitmap bitmap = new Bitmap(iconSize.Width, iconSize.Height);
using (Graphics g = Graphics.FromImage(bitmap))
{
    g.DrawIcon(SystemIcons.Error, new Rectangle(Point.Empty, iconSize));
}

But that just scales the 32 x 32 icon down into an ugly 16 x 16.

I've considered just pulling icons out of the VS Image Library, but I really want them to vary dynamically with the OS (XP icons on XP, Vista icons on Vista, etc.). I'm willing to P/Invoke if that's what it takes.

+1  A: 

Xml-docs for this constructor tells:

Duplicates the given icon, attempting to find a version of the icon
that matches the requested size.  If a version cannot be found that
exactally matches the size, the closest match will be used.  Note
that if original is an icon with a single size, this will 
merely create a dupicate icon.  You can use the stretching modes
of drawImage to force the icon to the size you want. 

I think that this icon has only one size (32x32) and way to get different size is to scale this icon to your size, as you made in your example.

Pavel Belousov
These icons definitely exist at a smaller size. If I can't access them through SystemIcons, that's fine, but I'd like to know if there's a way that works.
Andrew Watt
Sorry, could I ask, how do you know that these icons exist in smaller size?
Pavel Belousov
These are standard icons and standard sizes. You can see examples of them in use in the Windows UX Guidelines: http://msdn.microsoft.com/en-us/library/aa511277(v=MSDN.10).aspx.
Andrew Watt
A: 

You have to scale them yourself. The SystemIcons, as you found out, only have 32x32. You can easily scale them to 16 or 48 as needed. Use interpolation to get a nice bicubic resize. We've done this many times successfully to create very nice looking 16x16 versions and it works fine whether running XP or Vista or 7.

using (Graphics g = Graphics.FromImage(bitmap))   
{
    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
    g.DrawIcon(SystemIcons.Error, new Rectangle(Point.Empty, iconSize));   
}

Normally, though, we opt for the DrawImage method. Not sure if DrawIcon will make use of the interpolation mode or not!

Yadyn
+1  A: 

I wound up P/Invoking. It turns out that both LoadIcon and LoadImage exhibit the same (flawed, IMO) behavior as SystemIcons. But SHGetStockIconInfo, which is available on Vista and later, works as expected, returning the small, official, designer-crafted icons that I've been looking for.

On XP and earlier, I'm falling back to using the small icons provided in the VS Image Library.

If you're thinking about P/Invoking SHGetStockIconInfo yourself, I recommend taking a look at the Windows API Code Pack to see how.

Andrew Watt