windows - 在多 DPI 环境中将 HIMETRIC 转换为像素
问题描述
我的 UI 框架使用双精度值作为像素坐标,这在视网膜显示器上为我提供了很好的分数虚拟坐标。为此,我以 HIMETRIC 单位从 Windows 获取鼠标坐标。但是,我遇到了一个我无法弄清楚的错误。
我将 Surface Book 2 (3000x2000 @ 225%) 插入带有两个外接显示器 (1920x1080 @ 100%) 的底座。如果我在插入扩展坞的情况下登录 Windows(并将外接显示器 @ 100% 设置为主要显示器),我会收到正确的 HIMETRIC 坐标,该坐标可在外部显示器和视网膜显示器上工作。
但是,如果我在 Dock 未插入的情况下登录到 Windows,那么只有视网膜显示器,然后插入 Dock,然后运行我的应用程序 - 现在它接收由显示器的缩放因子缩放的HIMETRIC 坐标,这在我是主要的登录到 Windows。
我已将我的应用程序的 DPI 感知设置为 PerMonitorV2,这就是为什么我觉得每个系统的 DPI 比例设置甚至与我的应用程序相关如此奇怪的原因。
这是我用来从 HIMETRIC 转换的函数:
double fromHimetric(uint i)
{
return (double)i / 2540 * Monitor::DefaultDPI;
}
Monitor::DefaultDPI
是一个设置为 96 的常量。
我错过了什么吗?我需要在公式中添加系统比例因子吗?在这种情况下,当我登录 Windows 时,如何找出哪个显示器是主要显示器?因为无论我将窗口移动到哪个监视器,这似乎都保持不变,因为我收到的 HIMETRIC 值显然是按过去的值缩放的。
编辑:因为多显示器的东西很难在互联网上描述,所以我制作了一个小视频,展示了这个错误是如何为我表现出来的。https://www.youtube.com/watch?v=pTZiTZFXsc0
编辑 2:为了进一步澄清,我的应用程序完全尊重每个显示器的 DPI,我的所有 UI 都是矢量化的,因此它可以正确缩放,我处理WM_DISPLAYCHANGE
所有WM_DPICHANGED
这些东西。笔和触摸坐标在所有情况下都可以正常工作。
如果我最初启动计算机时,唯一会中断的是,我从鼠标获得的 HIMETRIC 坐标是GetPointerInfo()
由计算机启动时主要的显示器的显示比例缩放的。
我努力确保我能很好地处理多显示器多 DPI 情况。如果我忽略了一件简单的事情会破坏一切,我会感到非常愚蠢。
编辑 3:看看 Chrome 中的滚动条有多大。https://imgur.com/a/F3dFHAj
或 OBS 工作室:https ://imgur.com/a/11aG5Kw
他们似乎遭受了类似的错误。不知道他们的是否与 HIMETRIC 有任何关系,但这些元素的呈现方式会根据我启动计算机的方式而有所不同。
Win32 是否定义了启动监视器之类的东西?
编辑 4:我不使用的原因AtlHiMetricToPixel()
是PhysicalToLogicalPoint()
它们返回整数逻辑坐标,并且我特别希望在逻辑空间中使用双精度,因为我的整个 UI 都是基于矢量的。我自己做所有的缩放,它似乎工作正常,除了在这种情况下。:(
解决方案
对于任何对此感兴趣的人,我在这里得到了答案。
会话登录时主监视器的 DPI 为
HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics | AppliedDPI
我已经对其进行了测试,根据我的登录方式,它总是正确的。所以在我的情况下,我的应用程序只需要在启动时从注册表中读取它,然后使用它来调整鼠标的传入 HIMETRIC 坐标。
推荐阅读
- colors - 无法使用调色板用颜色填充对象
- c# - 如何将从 datagridview 显示的选定数据传递给 CrystalReportViewer
- javascript - 我可以在 django 项目中使用反应路由器吗?
- javascript - 从选中的单选按钮传递整数数组而不是数字字符串
- python - 在不知道确切长度的情况下从大型 csv 中选择行子集时使用 numpy.random.seed()
- ios - 如何在背景中将渐变颜色设置为 UIButton?
- r - 如何在 CentOS 中安装特定版本的 R 3.3.1
- javascript - 制作 React 状态数组的浅拷贝并修改该浅拷贝是否安全?
- python - 给np数组中的字符串赋值,转换为int,计算加权平均值
- prestashop-1.6 - 在帮助表单 Prestashop 中动态添加表单字段