关于winapi:GetSystemMetrics()为SM_CXSCREEN返回错误的值

GetSystemMetrics() returns wrong value for SM_CXSCREEN

我遇到了一个有趣的问题。 至少在Vista中,当桌面DPI设置未设置为100%时,getSystemMetrics(SM_CXSCREEN)返回错误的值。 例如,我在1366x768屏幕中尝试了150%,getSystemMetrics()返回911而不是1366(和1366 / 1.5?911)

根据MSDN,getSystemMetrics(SM_CXSCREEN)返回像素,因此我认为该值不受DPI设置的影响,但确实如此。 那么,有没有更安全的方法来找出真正的,未缩放的屏幕分辨率?


当您超过125%时,程序必须告知操作系统它可以识别DPI。 最好用清单来完成,如MSDN Library这篇文章中所述。


为了使您的应用程序了解dpi的make和manifest文件,并将以下文本放入其中。

1
2
3
4
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>


在从诸如GetSystemMetrics或GetClientRect之类的函数获取正确的像素度量之前,您的应用必须向操作系统声明其了解DPI,因此不会搞砸一切。

建议的方式已进行了几处更改。 有关更多详细信息,请参见MSDN文档。

从Windows 10开始:

1
::SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);

或从Windows 8.1起:

1
::SetProcessDpiAwareness(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);

或从Vista开始:

1
::SetProcessDPIAware();

调用此函数后,函数GetSystemMetrics等应将正确的值以像素为单位返回给您的应用。