如何知道 Windows HWND 的当前位图缩放因子? == 案例 1.0 ==== 案例 1.5 ==

问题描述

我有一个小的 C# 程序 HelloCs.cs,如下所示:

using System;
using System.Drawing;
using System.Windows.Forms;

class HelloWorld: Form
{
     public static void Main()
     {
          Application.Run(new HelloWorld());
     }
     public HelloWorld()
     {
          Text = "Hello World";
          BackColor = Color.White;

     }
     protected override void OnPaint(PaintEventArgs pea)
     {
          Graphics grfx = pea.Graphics;

          this.Width = 200;
          this.Height = 100;

          grfx.DrawString(
              $"({this.Width},{this.Height}) Hello,Windows Forms!",Font,Brushes.Black,0);

          base.OnPaint(pea);
     }    
}

== 案例 1.0 ==

认的 Windows 7 系统上运行时。它是这样显示的,没什么特别的:

enter image description here

窗口宽度和高度分别为 200 和 100。

== 案例 1.5 ==

当我将系统 DPI 缩放比例设置为 150%(并重新启动操作系统)时,C# 程序仍然像以前一样报告窗口宽度和高度,但是,窗口的实际屏幕大小(像素数)变为 300 和 150。这意味着, Windows 系统在我的窗口上应用了所谓的位图缩放

enter image description here

那么我的问题是:我怎么知道(在我自己的程序中,或者使用 HWND 句柄),系统是否对窗口应用了位图缩放,以及缩放因子是多少。

在 Window 10 上,事情变得更加复杂,因为根据 HWND 的当前驻留监视器,Windows 10 可能会对不同的 HWND 应用不同的缩放因子。

我希望得到一个适用于 Windows 7 和 10 的答案。

解决方法

经过一个月的调查,我发现这是一个非常复杂的问题。在 Windows 7、Windows 8.1 和 Win10.1607+ 上的情况都不同。

最后,我设法编写了一个演示程序(基于一个开源项目),可以由系统确定位图拉伸因子。

说话很便宜,所以这是我的工作代码: https://github.com/chjfth/window-finder-control

特点:

  • 在 Windows 7 和 Win10.1607+ 上,无论调用方程序本身是 DPI-unaware、SysDpi-aware 还是 Per-monitor-aware,我都能准确地分辨出来。
  • 在 Windows 8.1 ~ Win10.1511 上,调用程序必须每个监视器都可以准确地告诉它。这是因为缺乏对 Win81 的基本混合模式 DPI 缩放的 API 支持。

在下面查看我的演示 UI

图 1:

enter image description here

说明:

  • WinRect 通过调用 GetWindowRect 显示 RECT 值,即所谓的虚拟 RECT 大小。
  • 左上角的红色数字显示了调用程序“计算或推导出”的目标窗口的物理尺寸。

它们都是 400x241,所以目标窗口没有被位图拉伸。

图 2:在全局 DPI 缩放设置为 150% 的 Windows 7 上,物理 RECT 比虚拟 RECT 大 150%(按宽度或高度比较,宽度为 600 与 400)。因此,目标窗口被拉伸了 150%。

enter image description here

图 3:在 Win10.1909 上,我们还可以看到 150% 位图拉伸的窗口。

enter image description here

图 4:在 Win10.1909 上,我们甚至可以看到位图缩小的 HWND。当调用者是 SysDpi-aware(150%) 并且目标窗口也是 SysDpi-aware 但驻留在 100%-scaling 监视器上时,就会发生这种情况。

enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...