hardcodet / wpf-notifyicon

NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform
MIT License
830 stars 130 forks source link

Downscaling from the maximum icon size instead of picking the correct icon size from an icon package (.ico file). #75

Open devpelux opened 2 years ago

devpelux commented 2 years ago

I have an icon package with icons of 3 sizes: 64x64, 32x32, 16x16, the icon must be 16x16 in my case, but is always picked an icon with a higher resolution then downscaled to 16x16, even if i have added explicitly a 16x16 icon.

The downscaling degrades my icon, making it blurry, for example my 16x16 uses a cross of 1 pixel, but it displays a wrong downscaled icon that has a blurry 2 pixel cross.

tray

The only solution is to use a .ico file with only a 16x16 icon size, but this way doesn't support monitors with higher resolution that will upscale the 16x16.

tray2

HavenDV commented 2 years ago

What happens if the .ico file does not contain the required size(after your PR)?

devpelux commented 2 years ago

This

It resizes the next icon.
The 2 icons have different size because my 16x16 is actually a 15x15 to center the white line.

devpelux commented 2 years ago

It resizes the next icon. The 2 icons have different size because my 16x16 is actually a 15x15 to center the white line.

This is not a bug, if there isn't an icon to pick the only option is downscaling the next.

Lakritzator commented 2 years ago

Sorry for the delay, last Friday my family and me had gotten covid, and having a 6yo kid keeps you occupied...

I never wanted to close the issue already, as I know there are some additional things to do. But I forgot the standard behaviour when I merged 🤷‍♂️

We should write down what we want / expect etc. I think there is always room for improvement, it's not hard to read the .ico file ourselves and select the best option.

Also do not that one needs to enable dpi-awareness for their app to get some of the special features.

caesay commented 2 years ago

FYI this is how I pick an icon and give it to NotifyIcon at the moment:

var desiredSize = System.Windows.Forms.SystemInformation.SmallIconSize.Width;
var avaliableSizes = new[] { 64, 48, 40, 32, 24, 20, 16 };
var nearest = avaliableSizes.OrderBy(x => Math.Abs(x - desiredSize)).First();
var icon = new Icon(IconStream, new System.Drawing.Size(nearest, nearest));

notifyIcon.Icon = icon;

The current committed fix for this (3672b4e3c1e530596cd7c70b11e5a2002e9750e1) only attempts to address the problem when the icon is set through IconSource but this same mechanism is required for the Icon property to select the proper icon. The change also doesn't make an effort to detect the available sizes (is this important?).

I am not sure what can (or should) be done if someone passes in the wrong GDI icon. Eg. notifyIcon.Icon = new Icon(iconStream) will probably give you the wrong icon, can we correct it? and how to avoid making changes if the correct icon is already provided?

DarkPro1337 commented 2 years ago

This commit fixed an issue where, in a Windows UI at 100% scale, an icon that had a 16x16 version was 32x32 scaled down to 16x16 instead of the existing 16x16 version in the same ICO file. But now it ignores the Windows UI scaling fact, if you choose 125% or 150% the icon will stay at 16x16. Can it be fixed in the some way?

devpelux commented 2 years ago

Just for reminder:

To get the scaling factor:

PresentationSource source = PresentationSource.FromVisual(someVisual);

double scaleX, scaleY;
if (source != null) {
    scaleX = source.CompositionTarget.TransformToDevice.M11;
    scaleY = source.CompositionTarget.TransformToDevice.M22;
}

https://social.msdn.microsoft.com/Forums/vstudio/en-US/e987de11-d5c5-4b0e-abae-a6de64847c38/getting-scale-factor?forum=wpf

or this

https://stackoverflow.com/a/60987055