Winapi GetSystemMetrics()为SM\u CXSCREEN返回错误的值

Winapi GetSystemMetrics()为SM\u CXSCREEN返回错误的值,winapi,dpi,screen-resolution,Winapi,Dpi,Screen Resolution,我遇到了一个有趣的问题。至少在Vista中,当桌面DPI设置未设置为100%时,getSystemMetrics(SM_CXSCREEN)返回不正确的值。例如,我在1366x768屏幕上尝试了150%,getSystemMetrics()返回911而不是1366(和1366/1.5~911) 根据MSDN,getSystemMetrics(SM_CXSCREEN)返回像素,因此我认为该值不会受到DPI设置的影响,但确实如此。那么,有没有更安全的方法来确定真实的、无标度的屏幕分辨率呢?程序必须告诉

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


根据MSDN,getSystemMetrics(SM_CXSCREEN)返回像素,因此我认为该值不会受到DPI设置的影响,但确实如此。那么,有没有更安全的方法来确定真实的、无标度的屏幕分辨率呢?

程序必须告诉操作系统,当您超过125%时,它能够感知DPI以获得真实的分辨率。最好使用清单,如本文所述。

使您的应用程序了解dpi生成和清单文件,并在其中放入以下文本

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

真的

在从GetSystemMetrics或GetClientRect等功能获取正确的像素指标之前,您的应用程序必须向操作系统声明它了解DPI,因此不会把一切都搞糟

对建议的方式进行了一些更改。有关更多详细信息,请参阅MSDN文档

从Windows 10开始:

::SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
或从Windows 8.1开始:

::SetProcessDpiAwareness(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
或从Vista开始:

::SetProcessDPIAware();

调用此函数后,GetSystemMetrics等函数应以像素为单位向应用程序返回正确的值。

您从哪种应用程序调用此函数?我只是试着从C调用这个API,在Vista Business上以不同的DPI设置和不同的分辨率运行它,它在每个实例中都正确地报告了像素。它是一个VMware映像,所以可能会造成不同。它是一个普通的C++应用程序。没有标准框架,只有WinMain。始终建议您使用清单来设置流程的DPI感知。有三种类型的DPI感知:1)不知道(您认为世界始终是96 DPI)2)系统感知(您了解DPI,但认为世界始终是系统DPI,永远不会改变)3)每个监视器感知(您了解DPI,并且它可以在运行时改变)SetProcessDPIAware()使整个流程系统感知SetProcessDpiAwareness(…)允许您指定流程的感知模式SetThreadDPIAwarenesContext(…)启用子流程DPI感知