Andrew Watt
Andrew Watt

Reputation: 2767

Is there a way to get different sizes of the Windows system icons in .NET?

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.

Upvotes: 18

Views: 7951

Answers (3)

Sean Hanley
Sean Hanley

Reputation: 5727

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.

Size iconSize = SystemInformation.SmallIconSize;
Bitmap bitmap = new Bitmap(iconSize.Width, iconSize.Height);

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

Icon smallerErrorIcon = Icon.FromHandle(bitmap.GetHicon());

Be sure to check out the MSDN example here, especially their use of the DestroyIcon method to clean up the handle when you're done.

Upvotes: 14

Pavel Belousov
Pavel Belousov

Reputation: 1858

The documentation for this constructor overload says:

"Initializes a new instance of the Icon class and attempts to find a version of the icon that matches the requested size.

"If a version cannot be found that exactly matches the size, the closest match is used. If the original parameter is an Icon that has a single size, this method only creates a duplicate icon."

I think that this icon has only one size (32×32); and the only way to get different sizes is to scale this icon to your size, as in your example.

Upvotes: 1

Andrew Watt
Andrew Watt

Reputation: 2767

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.

Upvotes: 7

Related Questions