Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
542 views
in Technique[技术] by (71.8m points)

winapi - Getting an DPI aware correct RECT from GetWindowRect from a external window

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?

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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.

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:

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.

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.

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. 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.

    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.

  2. 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).

    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.

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...