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.