7
votes

I am using Visual Studio 2010, C#, on Windows 7.

I have added a notify control to my project and set it to an icon I have imported to the project. The icon image is really good looking if I just preview it, but once I run my code and see it in the system tray, then it's really terrible, like the sides are dotted instead of straight lines and so on. I have tried 16x16, 24x24, 32x32 and 48x48 of the same file but I am having terrible results.

Have I missed anything?

myNotifyIcon.Icon = SysDir.Properties.Resources.icon2_32_ico_rgba;
2
Screenshot required. Try limiting color content to 8bpp (256 colors).Hans Passant
what is the small icon size on this machine?David Heffernan
@Hans Passant : Its not just the color, but the size also that get deformed.syncis
@David Heffernan: I called an API to check the size for icons, it said 16xsyncis

2 Answers

16
votes

The problem with directly using the icon in your resources is that instead of choosing the right icon version in you icon file, the framework simply scales the default icon version to whatever size the notification area needs. That's why you are seeing jagged edges.

To get the best quality, you'll need to choose the right size in your icon by yourself.

First, instead of directly setting your NotifyIcon.Icon to an icon in your resources, create a new Icon instance. Doing so will allow you to choose a specific icon size in your icon resource. Using SystemInformation.SmallIconSize will get you the size the notification area needs.

So :

myNotifyIcon.Icon = new Icon(Properties.Resources.MyIcon, SystemInformation.SmallIconSize);

Now, SystemInformation.SmallIconSize always returns the right icon size, but only if your application is DPI-aware (otherwise, it always returns 16). If your application isn't DPI-aware, and it is used on a system where DPI-scaling is enabled, the line above will select the 16x16 icon in your resource, at it'll be scaled up to whatever size the notification area needs (in other words, ugly icon).

By making your app DPI-aware, SystemInformation.SmallIconSize will return the right size, taking into account DPI-scaling. For instance, if DPI-scaling is at 150%, SystemInformation.SmallIconSize will return 24 (16 × 1.5).

To make your app DPI-aware, simply add this to your app.manifest, inside the <asmv1:assembly> tag:

  <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
6
votes

Edit:

The info I am linking seems to be suspect at this point. Try it out, but if it isn't working, then I suggest you edit your question to post screenshots of all your experiments (each icon size and how it gets scaled).

Original:

32x32x256 is the right size and color depth according to this link:

http://www.hhhh.org/cloister/csharp/icons/

But you have to be very careful when constructing that image:

  • Take a 16x16x256 image, and get it to look nice
  • Double it to 32x32 (careful not to blur or resample if doing this in a paint program)

The reason is that Windows will "resize" the 32x32 image to 16x16 by simply throwing away 3/4 of the pixels. The link above demonstrates this phenomenon with a couple screenshots:

Before:

Before shrinking icon

After:

After shrinking icon

I'm not sure how much of the color-depth pickyness (256 colors only?)/resampling issues are still true on Windows 7, but it certainly seems to be the case on XP.