我需要为我的应用制作和加载多大尺寸的 ImageList 图标(考虑更高的 DPI)?

Posted

技术标签:

【中文标题】我需要为我的应用制作和加载多大尺寸的 ImageList 图标(考虑更高的 DPI)?【英文标题】:What size of ImageList icons do I need to make & load for my app (considering higher DPI)? 【发布时间】:2014-06-15 01:28:20 【问题描述】:

我有一个使用LVS_REPORT 样式创建的CListCtrl 控件(或Win32 中的ListView)。

我打算在其项目中显示图标:

但问题是我需要制作和加载多大尺寸的图标?

让我解释一下。从旧的 Win32 示例中,我可以看到每个人都使用 15x15 像素图标创建图像列表。但问题在于,在任何具有更高 DPI settings 的现代 PC 上,它看起来都非常像素化。因此,我一直在寻找一种动态方法来确定 CListCtrl 的图像列表的适当大小。

还有问题的第一部分,我最初应该制作多大的图标?

编辑 PS:既然DPI缩放出现了,你是怎么发现的?我目前正在使用以下方法:

//No error handling for brevity
HDC hDC = ::GetDC(hAppsMainWindowHandle);
int nCx = ::GetDeviceCaps(hDC, LOGPIXELSX);
int nCy = ::GetDeviceCaps(hDC, LOGPIXELSY);
::ReleaseDC(hAppsMainWindowHandle, hDC);

//I technically get horizontal & vertical scaling --
//can those be different?
double scalingCx = (double)nCx / 96.0;  //1.0 = 100%
double scalingCy = (double)nCy / 96.0;

字体缩放有什么不同吗?

【问题讨论】:

100% 字体缩放,96dpi,小图标为 16px,大图标为 32px。任何地方都没有 15 像素的图标。 【参考方案1】:

列表视图根据其模式使用“小”或“大”图像列表。在报告模式下,它使用“小”图像列表。您可以使用GetSystemMetrics() 获取“小”图像的尺寸,使用SM_CXSMICONSM_CYSMICON 指标(使用SM_CXICONSM_CYICON 获取“大”图像)。

请注意,如果您的应用不支持 DPI,则返回的值将是虚拟的/缩放的,因此要获得准确的值,请通过 SetProcessDPIAware()SetProcessDpiAwareness() 或 DPI 清单确保它支持 DPI。

更新:我刚刚遇到了这个函数,在编写 DPI 感知应用程序时可能对您有用:

LoadIconWithScaleDown()

制作更大的图像并让 API 将它们缩小到更小的尺寸。

【讨论】:

并非如此。 GetSystemMetrics(SM_CYSMICON) 对于默认的 100% DPI 返回 16,显然超过 1 个像素。如果我加载并显示高度为 16 像素的图像列表,则顶部像素会被截断,或者图标会有些挤压。显示的正确尺寸是 15x15。但我找不到任何系统指标值。 15x15 不是小图标的正确尺寸,16x16 是。我在我的 Win32 列表视图中使用 16x16(我不使用 MFC)并且它们工作正常而不会被挤压。我什至使用 20x20(或 24x24,我现在忘记了),这会导致列表项高度增加,而且它们也可以正常工作。所以可能是 CListCtrl 的问题,而不是底层的列表视图。 LoadIconWithScaleDown 非常简洁。当然是远景了。确实需要选择可用的图标大小。并且仍然会导致不可避免的缩放伪影。 好的,你可能有一点。我认为 15px 是上下文菜单的图标高度。 (我也必须对它们进行缩放。) 15x15 不是 Win32 API 中任何地方的标准图像尺寸。标准尺寸为 16x16、24x24、32x32 和 48x48。【参考方案2】:

报告样式列表视图需要小图标,即带有SM_CXSMICON by SM_CYSMICON 指标的图标。假设您的应用具有高 DPI 感知能力,那么这些指标的实际值取决于用户选择的字体缩放或 DPI 设置。所以在前面你不知道应该使用什么尺寸的图标。您必须在运行时查询系统指标,并使用适当大小的图标。

现在,您在可执行文件中包含的图标大小取决于您希望支持的 DPI 设置。回到 XP 时代,您可以合理地预期会遇到 100% 和 125% 的字体缩放。如今,高密度显示面板很常见,您确实需要支持更大的比例。至少 150% 和 200%,很可能是 175%。

我能找到的最接近指南的是这篇 MSDN 文章:http://msdn.microsoft.com/en-US/library/windows/desktop/dn742485.aspx

这篇文章是围绕 Vista 时间框架编写的,并且已经显示了它的时代。我认为您必须以这些文章为指导,并适应当时的硬件。

您还会发现人们在上面列出的整数之间以及我链接到的文章中以字体缩放值运行他们的机器。我的一位同事以 120% 的速度运行。有趣的是,这突出了我们代码中的各种错误,因此让某人狗食你的程序总是有用的。

当您在运行时构建图像列表时,请根据系统指标调整它们的大小。并尽量避免缩放图标。例如,如果系统指标建议使用 18px 图标,而您只有 16px 和 20px 图标,则制作一个新的 18px 图标。用透明像素填充图像,并将 16px 图标 blit 到这个 18px 图像的中间。从中制作图标。这种方法将避免混叠问题。

【讨论】:

谢谢。问题就像您指出的那样,您不知道用户将以何种缩放比例运行 UI。如果我愿意,我可以在我的 Windows 8.1 中指定 115%。 (有趣的是,即使是 Windows 资源管理器也不能始终正确处理它。)因此,无法使用一组“漂亮”的 Photoshop 缩放图标来预测这些设置中的每一个。不幸的是,即使在今天的操作系统中,微软仍然“没有得到”并且没有像样的 API 来进行缩减。 LoadIconWithScaleDown 正如您在上面指出的那样仍然很糟糕,仍然会导致“看起来很有趣”的工件(即使在我的 8.1 的 Windows 资源管理器中也是如此。) 我解释了如何处理它。在运行时查找图标大小。找到您拥有的最大图标资源,但小于该资源。根据正确大小的较小资源制作一个新图标,并且边缘周围有透明边框。我的最后一段。当你这样做时,你的应用程序可以在任何这些非标准缩放中运行。 没有像样的方法来缩小规模。这是一项不可能完成的任务。这就是为什么你需要提供很多版本的图标。我的应用附带了 16、20、24、32 和 48 像素版本的工具栏图标。我使用所描述的技术来显示适合小图标大小的最大的。它工作得很好。这确实是您唯一的选择。 有一种方法可以缩小它们。只是MS没有为此提供API。 Photoshop 和其他软件可以很好地做到这一点。无论如何,我更新了我的原始帖子。这是您获得当前比例因子的方式吗? 没有办法可靠且良好地缩小一般光栅图像。至于您提出的新问题,我认为您不需要在这里知道,但是是的,它是 LOGPIXELSX。无论如何,我想我回答了你提出的问题。我猜你对这两个答案都不感兴趣,但这取决于你。

以上是关于我需要为我的应用制作和加载多大尺寸的 ImageList 图标(考虑更高的 DPI)?的主要内容,如果未能解决你的问题,请参考以下文章

我想为我的网站制作一个漂亮的百分比预加载器,但我必须使用 Flash 吗?

为我的 iPhone 应用程序制作登录屏幕

更快地加载firebase图像数据

需要为我的iOS游戏制作一个DLC“包”系统

如何在我的 Web 应用程序中实现 REST。我想为我的网站制作一个休息 API?

如何用你的不同尺寸的子视图制作 UIStackView?