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
388 views
in Technique[技术] by (71.8m points)

python - GetWindowRect too small on Windows 7

The actual problem I'm trying to solve is, I want to automatically find out the size of the margins around windows. If you can find a better way, please by all means answer that instead of this.

To do this I decided to take a screenshot of a test window and measure the margins. This is simple enough, as I expect no margins will ever be bright pink, but I admit it's a hack. I use GetWindowRect (py) to get the bounding box, and PIL to grab a screenshot and crop to the bounding box. The problem is that while the crop operates correctly, the bounding box is not accurate. The Windows 7 "Snipping Tool" gets the correct dimensions. How may I do the same?

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

My first thoughts were listed below but if, as you state, you're certain that GetWindowRect is returning incorrect values, see RESOLUTION further down.


"What's wrong with GetSystemMetrics(SM_CXBORDER) and GetSystemMetrics(SM_CYBORDER)?

The method you're using seems a very roundabout way of doing it and, if you can call GetWindowRect(), I'm pretty certain you can call GetSystemMetrics() as well.

One other possibility is to use GetWindowRect to get the entire bounding rectangle for the window and GetClientRect to get the bounding rectangle for the client (non-border) area.

This should give you something like (100,200),(1000,900) and (112,227),(988,888) respectively and you can work out the top border as 227-200, bottom as 900-888, left as 112-100 and right as 900-888 (27,12,12,12).


RESOLUTION:

A bit of investigation turns up this. It's a thread from 2006 stating that you might not get the correct values from GetWindowsRect. The thread that pointed me to this stated:

Apps under Vista that are not linked with WINVER=6 will receive a misleading set of values here, that do not account for the extra padding of "glass" pixels Vista Aero applies to the window. This appears to happen even in Aero Basic (without Glass) to retain sizing consistency. The workaround (if you don't want to set WINVER=6) seems to be to dynamically bind to dwmapi.dll and use GetProcAddress() to obtain the DwmGetWindowAttribute() function, and call it with the DWMWA_EXTENDED_FRAME_BOUNDS argument to request the genuine window frame dimensions.

So basically, use something like (you may have to use ctypes to do this from Python):

RECT r;
HRESULT stat = DwmGetWindowAttribute (
    hwnd,
    DWMWA_EXTENDED_FRAME_BOUNDS,
    &r,
    sizeof(r));

and that should give you the correct bounding rectangle.


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

...