每个监视器DPI感知Windows系统映像列表

Mar*_*ryl 6 winapi winforms dpi-aware

如何检索给定DPI的系统映像列表?

当应用程序是系统DPI感知时,SHGetFileInfo类似的函数返回正确缩放的系统映像列表的句柄.C++示例:

handle =
  SHGetFileInfo(L"", 0, &fileInfo, sizeof(fileInfo),
                SHGFI_SYSICONINDEX | (large ? SHGFI_LARGEICON : SHGFI_SMALLICON));
Run Code Online (Sandbox Code Playgroud)

但是,对于每个监视器的DPI感知,这还不够,因为应用程序可以在不使用系统DPI的监视器上运行(或者应用程序可以有多个窗口,每个窗口在不同的监视器上,具有不同的DPI).

例如,在168 DPI(175%变焦)监视器上,使用标准96系统DPI,您可以获得小的未缩放16x16图标:

未缩放的系统图标

所以我希望,有SHGetFileInfo(或类似的)DPI感知变体,其他功能的DPI识别变体的方式如下:

Mar*_*ryl 3

作为一个快速解决方案,我最终使用了SHGetImageList@MickyD的建议

正如函数文档中提到的(以及@JonathanPotter的建议)

指针IImageList类型,例如ppv参数中返回的指针类型,可以根据HIMAGELIST需要强制转换为 an;例如,用于列表视图。

因此,我SHGetImageList通过调用 for 来收集所有可用的系统映像列表大小0..SHIL_LAST

对于每个返回的图像列表,我使用查询其图标大小ImageList_GetIconSize并将其全部缓存。

然后,当特定 DPI 需要图像列表时,我会选择最接近的可用尺寸。

一个明显的缺点是,在具有高系统 DPI 的多显示器系统上,但只有一个低 DPI 显示器时,无法检索低 DPI 显示器的合理大小的小图标。