从外部窗口从 GetWindowRect 获取 DPI 感知正确的 RECT [英] Getting an DPI aware correct RECT from GetWindowRect from a external window

查看:33
本文介绍了从外部窗口从 GetWindowRect 获取 DPI 感知正确的 RECT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作 DPI Aware 应用程序,但我需要对来自其他应用程序的 HWND 执行 GetWindowRect.我的问题是这在同样支持 DPI 的应用程序上运行良好,但是我如何检测 HWND 句柄是否是 DPI 虚拟化的,例如缩放以便我可以自己缩放?或者是否有其他我错过的 API 可以从另一个进程的 HWND 以 DPI 感知方式为我提供窗口大小?

I'm in the process of making an application DPI Aware but I have a need to do a GetWindowRect on HWNDs from other applications. My problem is this works fine on applications that are also DPI Aware but how do I detect if the HWND handle is DPI virtualized e.g. scaled so I can scale it myself? Or are there other APIs I've missed which will give me the size of the window in a DPI aware way from a HWND from another process?

我已经尝试过 LogicalToPhysicalPoint 但似乎总是失败,可能是因为 HWND 不属于我的应用程序.

I've tried the LogicalToPhysicalPoint but that always seem to fail, possibly because the HWND doesn't belong to my application.

推荐答案

这不是实际问题.如果您将流程标记为高 DPI 感知,那么系统将不再进行任何类型的 DPI 虚拟化,并且 API 将不再就实际值对您撒谎.

This is not an actual problem. If you mark your process as high-DPI aware, then the system will no longer do any sort of DPI virtualization and the APIs will no longer lie to you about the actual values.

特别是,如果您从高 DPI 感知应用程序调用 GetWindowRectGetClientRect,您将获得屏幕坐标中的实际值.这不仅适用于属于您的应用程序进程的窗口,而且适用于属于其他进程的窗口,无论其他进程的 DPI 感知设置如何.

In particular, if you call GetWindowRect or GetClientRect from a high-DPI aware application, you will get the actual values in screen coordinates. This will be true not only for windows belonging to your application's process, but also for windows belonging to other processes, regardless of that other process's DPI awareness setting.

从 Windows 8.1 开始,PhysicalToLogicalPointLogicalToPhysicalPoint 函数不再是必需的,实际上什么也不做.这两个函数的文档明确指出:

As of Windows 8.1, the PhysicalToLogicalPoint and LogicalToPhysicalPoint functions are no longer necessary and don't actually do anything. The documentation for these two functions calls this out explicitly:

在 Windows 8.1 中,系统和进程间通信的额外虚拟化意味着对于大多数应用程序,您不需要这些 API.因此,在 Windows 8.1 中,PhysicalToLogicalPointLogicalToPhysicalPoint 不再转换点.系统将所有点返回给应用程序自己坐标空间中的应用程序.

In Windows 8.1, the additional virtualization of the system and inter-process communications means that for the majority of applications, you do not need these APIs. As a result, in Windows 8.1, PhysicalToLogicalPoint and LogicalToPhysicalPoint no longer transform points. The system returns all points to an application in its own coordinate space.

最后一句话只是我上面所说的一种不同的措辞方式.系统根据调用者的DPI感知返回值.如果您的进程具有高DPI感知,那么您将获得真实值.您不需要自己缩放值.如果您不了解高 DPI,那么您很可能会在实际值方面被骗.但这是有道理的,因为假设您无法处理真相,也不会做出适当的反应.

The last sentence is just a different way of phrasing what I said above. The system returns values according to the DPI awareness of the caller. If your process is high-DPI aware, then you will get the real values. You do not need to scale the values yourself. If you are not high-DPI aware, then you are subject to being lied to about the actual values. But that makes sense, because it is assumed that you cannot handle the truth and will not react appropriately.

为了清楚起见,我应该指出,从 Windows 8.1 开始(并在 Windows 10 中继续),现在实际上有两个级别的高 DPI 意识:

Just to be clear, I should point out that there are actually two levels of high-DPI awareness now, as of Windows 8.1 (and continued in Windows 10):

  1. 第一个级别是在 Windows Vista 中引入的,具有高 DPI 意识.这由应用程序清单文件中的 true 设置指示,这仅意味着您(应用程序)能够处理设置为 system 的 DPI96 DPI 的经典默认设置之外的其他内容.

  1. There is the first level, introduced way back with Windows Vista, of high-DPI awareness. This is indicated by a setting of true in the application's manifest file, and it just means that you (the application) is able to deal with a system DPI that is set to something other than the classic default of 96 DPI.

根据以上知识,我们知道,如果具有此 DPI 感知设置的进程调用返回屏幕坐标的 API 函数,它将接收系统 DPI 形式的值.

Based on the above knowledge, then, we know that if a process with this DPI-awareness setting calls an API function that returns screen coordinates, it will receive the values in terms of the system DPI.

然后是 Windows 8.1 引入的新级别,每显示器高 DPI 感知.这由应用程序清单中的 True/PM 设置指示,这意味着您(应用程序)能够处理具有不同 DPI 设置的不同显示器.换句话说,虽然仍然存在系统默认 DPI(它可能是 96 DPI 或其他东西),但可能有连接到系统的监视器使用不同的 DPI 设置(不同于系统 DPI 的设置).

Then there is the new level, introduced with Windows 8.1, of per-monitor high-DPI awareness. This is indicated by a setting of True/PM in the application's manifest, and it means that you (the application) is able to deal with different monitors having different DPI settings. In other words, while there is still a system default DPI (and it may be 96 DPI or it may be something else), there may be monitors attached to the system that use a different DPI setting (something other than the system DPI).

再次,基于以上理解,我们知道,如果一个具有 per-monitor high-DPI 感知的进程调用一个返回屏幕坐标的 API 函数,它将接收到相对于包含的显示器的 DPI 的实际坐标有问题的窗口.

Again, based on the above understanding, we know that if a process that is per-monitor high-DPI aware calls an API function that returns screen coordinates, it will receive the actual coordinates relative to the DPI of the monitor that contains the window in question.

如果您的进程根本不知道 DPI(清单中没有设置,或者 false),那么当您调用返回屏幕坐标的 API 函数时,您将收到基于缩放/虚拟化的坐标全系统 DPI 为 96 DPI.

If your process is not DPI aware at all (no setting in the manifest, or false), then when you call API functions that return screen coordinates, you will receive the coordinates scaled/virtualized based on a system-wide DPI of 96 DPI.

这篇关于从外部窗口从 GetWindowRect 获取 DPI 感知正确的 RECT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆