在多DPI环境中将HIMETRIC转换为像素

时间:2018-10-17 09:24:23

标签: windows winapi coordinates dpi multiple-monitors

我的UI框架对像素坐标使用双精度值,这使我在视网膜显示器上获得了很好的分数虚拟坐标。为此,我从Windows以HIMETRIC单位获得了鼠标坐标。但是,我遇到了一个我不知道的错误。

我将Surface Book 2(3000x2000 @ 225%)插入带有两个外部显示器(1920x1080 @ 100%)的扩展坞中。如果我在插入扩展坞的情况下登录Windows(并且将外部监视器@ 100%设置为主要监视器),则我会收到正确的HIMETRIC坐标,该坐标在外部和视网膜显示器上均可使用。

但是,如果在拔出底座的情况下登录Windows,则只有 视网膜监视器,然后插入底座,然后运行我的应用程序-现在它收到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和{{1} },所有这些东西。笔和触摸坐标在任何情况下都可以正常工作。

如果我最初在未对接的情况下启动计算机,唯一会破坏的是是我从WM_DPICHANGED得到的鼠标 的HIMETRIC坐标被缩放。显示器的显示比例,它是计算机启动时的主要显示比例。

我一直在努力确保自己能很好地处理多监视器多DPI情况。如果有一件我忽略的简单事情破坏了一切,我会感到很傻。

编辑3:查看Chrome中滚动条的大小。 https://imgur.com/a/F3dFHAj

或OBS工作室:https://imgur.com/a/11aG5Kw

他们似乎遭受类似的错误困扰。不知道他们是否与HIMETRIC有任何关系,但是根据我如何启动计算机,这些元素的呈现方式有所不同。

Win32是否定义了类似启动监视器的内容?

编辑4:我之所以不使用GetPointerInfo()AtlHiMetricToPixel()是因为它们返回整数逻辑坐标,并且我特别希望在逻辑空间中加倍,因为整个用户界面是基于矢量的。我自己进行了所有缩放操作,除了在这种情况下,它似乎工作正常。 :(

1 个答案:

答案 0 :(得分:1)

对于任何对此感兴趣的人,我都会得到答案here

会话登录时主监视器的DPI位于

HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics | AppliedDPI

我已经对其进行了测试,并且始终正确,这取决于我的登录方式。因此,对于我来说,我的应用只需在启动时从注册表中读取该信息,然后使用它来调整鼠标的传入HIMETRIC坐标。