2014-07-03 123 views
1

我试图在MSDN上找到这个答案,但我没有清楚地知道这是如何工作的。我所有的工作都在Windows 8.1上。Windows设备坐标与虚拟坐标

这是我的问题。我正在使用高分辨率显示器3200x1800的笔记本电脑。我一直在使用EnumDisplayMonitors来获取屏幕的边界矩形。

这似乎工作正常,如果我的显示设置是默认的。但我注意到,当我改变窗口显示设置以提供更大的文本时,EnumDisplayMonitor返回的分辨率发生变化。而不是得到3200x1800我会得到2133x1200。

我猜,因为我要求较大的文本,Windows选择将屏幕表示为较小的分辨率。

看来,如果我看虚拟屏幕属性,所有内容都以我的屏幕的实际坐标表示,即3200x1800。但用于获取窗口和监视矩形的API似乎在这个“其他”坐标空间上运行。

是否有任何文档/ Windows API来处理这些“其他坐标”和“虚拟坐标”之间的转换?即如果我想让EnumDisplayMonitor或GetMonitorInfo给我真正的屏幕坐标,我怎样才能将2133x1200转换为3200x1800?

回答

4

您已将视频适配器的DPI提高到150%(每英寸144点)以保持文本可读性并避免使用窗口大小的邮票。这种高分辨率显示器非常必要。但是你还没有告诉Windows你的程序知道如何处理它。

因此,它假定你的程序是一个从未被设计成在这种显示器上运行的程序。它对你有帮助和谎言。它让你的程序把它的输出渲染到一个内存缓冲区,然后获得这个输出,重新调整它150%并将它复制到视频适配器。这是你可以看到的东西,如果你把程序的输出放在一个不需要这种缩放的程序旁边,那么文本看起来就很模糊,就像记事本一样。

当然,当你询问屏幕的大小时,它就在于你。它告诉你它比实际小150%。因此,重新缩放后,您创建的窗口将填满屏幕。

这是一切都很好,但当然不理想,你的程序看起来不像它应该那样好。 You have to tell Windows知道如何处理更高的分辨率。请注意,这看起来比实践中更容易。让文本看起来很脆弱是微不足道的,它是有问题的位图。而且一般来说,这是一个繁琐的错误来源,即使是big companies can get this wrong

+0

啊这是我想的答案。我感到非常困惑,因为无论我改变了什么,从枚举监视器设备收到的DPI始终是相同的。但决议不断变化。听起来像Windows正在骗我。所以,现在对于一个*后续问题,如果我现在更愿意让我的应用程序DPI *不知道*,那么确定DPI的最简单方法是什么?有什么方法可以计算它吗? – anoneironaut

+0

如果你喜欢被骗,那么你只是不在乎它可能是什么。你只需假设96 dpi。 –

+0

但我想知道各种显示器和窗口的真实分辨率是多少。好像所有的窗口提供这样做的API只有在我的应用程序是“DPI Aware”时才有效。所以我想知道如果我不是DPI Aware,我可以做这些转换。 – anoneironaut

0

在我开始回答之前,让我问:你真的想要做什么?或更具体 - 为什么你需要知道显示器分辨率?执行此操作的标准方法是调用GetWindowRect(GetDesktopWindow(), &rect)我不确定屏幕坐标是否基于DPI设置进行了更改 - 但您应该尝试使用GetMonitorInfo而不是GetMonitorInfo,因为后者适用于更高级的内容。如果GetWindowRect仍然返回缩放的矩形,请根据需要调用DPtoLPLPtoDPother mapping coordinate function

如上所述调整显示设置时,实际上是在更改屏幕的DPI设置。因此,某些API进入兼容模式,以便它们允许应用创建更大的元素和窗口,而无需了解此设置。

为什么您需要知道实际的屏幕分辨率,因为当DPI缩放更改时,大多数窗口API都会相应地运行?

我怀疑你可以打电话SetProcessDPIAware或清单文件等效。但首先阅读this MSDN article以了解DPI缩放。