8

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;
dandan78
  • 13,328
  • 13
  • 64
  • 78
syncis
  • 1,395
  • 4
  • 25
  • 43

3 Answers3

17

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>
idmadj
  • 2,565
  • 2
  • 19
  • 23
  • Do you think this concept should be applied to WPF window icons? I've seen that in WPF the icons don't usually scale well despite me generating .ico files with ranges from 16x16 all the way up to 256x256. – Alexandru Jun 07 '15 at 22:26
  • Great, Thank you very much! – Ahmed Osama Jan 29 '18 at 23:26
6

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.

Merlyn Morgan-Graham
  • 58,163
  • 16
  • 128
  • 183
  • This link seems to have more info on the various color depths and sizes, though no mention of the Notification Icon: http://msdn.microsoft.com/en-us/library/ms997636.aspx – Merlyn Morgan-Graham Sep 21 '11 at 08:11
  • 1
    certainly should not be 32px. Should be the small icon size, typically 16px.on size, typically 16px. – David Heffernan Sep 21 '11 at 11:24
  • I have tried just doing the 16x picture as the icon, and its looks "most" normal. – syncis Sep 21 '11 at 11:42
  • scaling small raster images leads to dreadful results. Always best to use the right size. I have some experience in this. – David Heffernan Sep 21 '11 at 21:36
  • 1
    @David: Yes scaling always leads to less than perfect results. But according to that article, it scales it for you. You don't have a choice - you just have to work around it. – Merlyn Morgan-Graham Sep 21 '11 at 22:11
  • Not in my experience. Although that's with native API. I'd be astounded if C# wrapper differed. Give it the right size. I think the article you link to is utterly bogus. – David Heffernan Sep 21 '11 at 22:16
  • 1
    @David: I won't argue with your experience or defend the article. Just wanted to make sure you were disagreeing with the point I was making, rather than points I wasn't trying to make :) I agree with Hans' "screenshot required" comment at this point. Multiple... – Merlyn Morgan-Graham Sep 21 '11 at 22:27
  • Did anyone try this? Does this still work in Win10? I couldn't get it to work but maybe I just misunderstand something. It seems to me that windows is not using 'nearest neighbor' for rescaling. – Xan-Kun Clark-Davis Jan 18 '23 at 23:52
0

I use NotifyIcon in a C# WinForms application and no matter what the icon I use contains, after 2 resolution changes it ends up blurry.
My best guess is, that windows doesn't actually rescale the original every time but rescales the (already rescaled) version from the icon cache.

The only solution I found so far was setting the icon again after a resolution/dpi change:

SystemEvents.DisplaySettingsChanged += (sender, eventArgs) => {
   trayIcon.Icon = MyIcon;
};

I tried all kind of resolutions and bit depths in the icons but they all got blurred eventually. Now I only use a single 16x16 32b image in the icon and so far it works great on all tested displays.

Xan-Kun Clark-Davis
  • 2,664
  • 2
  • 27
  • 38