当"Make it easier to read what's on screen"为 150% 时,Screen.Width 报告了错误的分辨率



问题
Screen.Width/Screen.Height报告的分辨率有时(很少)小于"控制面板"中报告的分辨率。Delphi报告的分辨率总是比实际分辨率小(大约1/3)。这"很有道理"。我的意思是,它似乎是普通计算机中用于分辨率的"整数"之一,比如1280x720。

我无法在我的系统中复制这个,但我从第三方计算机上得到了一些屏幕截图。

最近我使用

 var MonInfo: TMonitorInfo;
 begin
  MonInfo.cbSize := SizeOf(MonInfo);
  GetMonitorInfo(MonitorFromWindow(Application.MainForm.Handle, MONITOR_DEFAULTTONEAREST), @MonInfo);
  Result:= MonInfo.rcMonitor.Right;

它返回与Screen.Width/Screen.Height相同(错误)的结果。仅在几个系统上报告了这一点(3-4)。其中两个被外部监视器/电视钩住了。

详细信息
Delphi显示的分辨率:1280x720
控制面板显示的分辨率:1920x1080
DPI:96
更容易阅读屏幕上的内容:150%
测试项目:我刚开始一个新的默认项目;ObjInspector中没有更改任何属性。用C++编写的一个小测试程序也显示了错误的分辨率
Delphi XE

问题
哪个Delphi函数将返回正确的分辨率,或者我如何根据Screen.Width(Screen.Height)报告的分辨率计算正确的分辨率?


已移至此处:
如何在高DPI系统中获得真实的屏幕分辨率?

您的程序不会声明自己具有高dpi意识。因此,它受制于一种称为DPI虚拟化的兼容模式。系统将为您的程序提供虚假的屏幕尺寸和坐标,然后将程序的显示比例调整为真实尺寸。

除了给你提供你无法识别的屏幕尺寸外,一个更重要的问题是DPI虚拟化会导致你的程序因混叠而显得模糊。系统会尽最大努力缩放程序以适应用户所需的DPI,但缩放光栅图像时不可能没有一些混叠。

一些有用的链接:

  • MSDN:用户界面,高DPI意识
  • MSDN:高DPI
  • MSDN:教程,编写高DPI Win32应用程序
  • 堆栈溢出:当Windows字体比例大于100%时,如何使GUI表现良好

如果您希望避免DPI虚拟化,并让您的程序获得真实的屏幕尺寸,那么您应该将程序标记为高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>

TScreen直接从Windows获取其分辨率值,因此Windows是"撒谎"的。你的GetMonitorInfo()测试证明了这一点。我的猜测是,当你的应用程序出现这个问题时,它很可能是在兼容模式下运行的,尤其是如果你的应用在现代Windows版本上不是高DPI感知的。这需要您的应用程序使用特殊的清单值和API调用。

最新更新