通知图标一旦出现在系统托盘中,图像质量变得很糟糕。

8
我正在使用Windows 7上的Visual Studio 2010,C#。我在我的项目中添加了一个通知控件,并将其设置为我导入到项目中的图标。如果我只是预览它,图标图像看起来非常漂亮,但一旦我运行代码并在系统托盘中看到它,那么它就变得非常糟糕,比如边缘是点而不是直线等。我尝试过16x16、24x24、32x32和48x48大小的同一文件,但效果非常差。我有什么遗漏吗?
myNotifyIcon.Icon = SysDir.Properties.Resources.icon2_32_ico_rgba;

2
需要截图。尝试将颜色内容限制为8bpp(256种颜色)。 - Hans Passant
1
这台机器上的小图标尺寸是多少? - David Heffernan
@Hans Passant:不仅是颜色,大小也会变形。 - syncis
@David Heffernan:我调用了一个API检查图标的尺寸,它显示为16x。 - syncis
3个回答

17

直接使用资源中的图标存在问题,因为框架不会选择正确版本的图标文件,而是将默认版本的图标按照通知区域需要的大小进行缩放,这就是为什么你看到锯齿状的边缘的原因。

为了获得最佳质量,你需要自己选择正确的图标大小。

首先,不要直接将NotifyIcon.Icon设置为资源中的图标,而是创建一个新的Icon实例。这样做可以让你在图标资源中选择特定的图标大小。使用SystemInformation.SmallIconSize将为你提供通知区域所需的大小。

因此:

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

现在,SystemInformation.SmallIconSize永远返回正确的图标大小,但只有当您的应用程序是DPI感知的时(否则,它总是会返回16)。如果您的应用程序不是DPI感知的,并且在启用了DPI缩放的系统上使用,则上面的代码将选择您资源中的16x16图标,并将其缩放到通知区域所需的任何大小(换句话说,这样的图标不美观)。

通过使您的应用程序成为DPI感知的,SystemInformation.SmallIconSize将返回正确的大小,考虑到DPI缩放。例如,如果DPI缩放为150%,SystemInformation.SmallIconSize将返回24(16× 1.5)。

要使您的应用程序成为DPI感知的,请在<asmv1:assembly>标记内简单地将以下内容添加到您的app.manifest文件中:

  <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>

你认为这个概念应该应用于WPF窗口图标吗?我发现在WPF中,尽管我生成了从16x16到256x256的范围的.ico文件,但图标通常不会很好地缩放。 - Alexandru
太棒了,非常感谢! - Ahmed Osama

6

编辑:

目前我链接的信息似乎有问题。您可以尝试使用,但如果不起作用,建议您编辑您的问题并发布所有实验的截图(每个图标大小和如何缩放)。

原文:

根据此链接,32x32x256是正确的大小和颜色深度:

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

但在构建该图像时必须非常小心:

  • 获取一个16x16x256的图像,并使其看起来漂亮
  • 将其扩大到32x32(如果在绘画程序中进行此操作,请小心不要模糊或重采样)

原因是Windows会通过简单地丢弃3/4的像素来“调整”32x32图像大小为16x16。上面的链接用一些屏幕截图演示了这种现象:

之前:

Before shrinking icon

之后:

After shrinking icon

我不确定在Windows 7上还有多少颜色深度挑剔性(仅256种颜色?)/重采样问题是正确的,但在XP上似乎肯定是这种情况。


1
肯定不应该是32像素。应该是小图标大小,通常为16像素。 - David Heffernan
我尝试过将16x图片作为图标,它看起来“最”正常。 - syncis
1
@David:是的,缩放总是会导致不完美的结果。但根据那篇文章,它会为你自动进行缩放。你没有选择,只能在此基础上进行调整。 - Merlyn Morgan-Graham
1
@David:我不会质疑你的经验或为这篇文章辩护。只是想确保你是在反驳我所提出的观点,而不是其他我并没有尝试提出的观点 :) 我同意Hans在这一点上的“需要截图”评论。多个... - Merlyn Morgan-Graham
有人试过这个吗?在Win10上还有效吗?我无法使其工作,但也许是我误解了什么。对我来说,似乎Windows没有使用“最近邻”进行重新缩放。 - Xan-Kun Clark-Davis
显示剩余3条评论

0

我在一个C# WinForms应用程序中使用NotifyIcon,无论我使用什么图标,经过2次分辨率更改后,它最终都会变得模糊。
我最好的猜测是,Windows实际上并不会每次重新缩放原始图标,而是从图标缓存中重新缩放(已经缩放过的)版本。

到目前为止,我找到的唯一解决方案是在分辨率/ dpi更改后再次设置图标:

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

我尝试了各种分辨率和位深度的图标,但最终它们全部都会变得模糊。现在我只使用一个16x16 32位图像作为图标,到目前为止在所有测试的显示器上效果都很好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接