winforms - 每个监控器可识别DPI的Windows系统镜像列表

原文 标签 winforms winapi dpi-aware

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

当应用程序可识别系统DPI时,SHGetFileInfo和类似功能会将句柄返回到正确缩放的系统映像列表。 C ++示例:

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


但是仅凭每个监视器的DPI意识是不够的,因为该应用程序可以在不使用系统DPI的监视器上运行(或者该应用程序可以具有多个窗口,每个窗口在不同的监视器上具有不同的DPI)。

例如,在带有标准96系统DPI的168 DPI(175%缩放)监视器上,您会看到小的未缩放的16x16图标:

unscaled system icons

因此,我希望SHGetFileInfo(或类似名称)具有DPI感知变体,以及其他功能的DPI感知变体,例如:


GetSystemMetricsForDpi表示GetSystemMetrics
SystemParametersInfoForDpi表示SystemParametersInfo
OpenThemeDataForDpi表示OpenThemeData

最佳答案

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

如功能文档中所述(以及@JonathanPotter的建议):


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


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

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

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

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

相关文章:

forms - 检查什么在Powershell中关闭了Windows窗体

winapi - 在Windows上将结构与Golang syscall一起使用?

c# - 如何将应用配置为在DPI设置较高(例如150%)的计算机上正确运行?

c# - 如何使用Winforms在多列模式下将项目添加到TreeViewAdv

c# - 有没有一种方法可以将一组字段划分为一个类中的“子结构”

c# - 不使用OnPaint()绘制时的双缓冲:为什么不起作用?

c++ - C++中的嵌入式资源

c++ - 如何将HTML字符串加载到嵌入式WebBrowser控件?

c++ - Winapi在不同机器上缩放

c# - 知道DPI和Rect