在Windows 7上GetWindowRect太小
我试图解决的实际问题是,我想自动找出窗口边缘的大小。如果你能找到更好的办法,请尽一切办法回答这个问题,而不是这个。在Windows 7上GetWindowRect太小
为此,我决定截取测试窗口并测量边距。这很简单,因为我预计没有利润率会变成明亮的粉红色,但我承认这是一种黑客行为。我使用GetWindowRect(py)获取边界框,并使用PIL获取屏幕截图并剪裁到边界框。问题是,当作物正常运行时,边界框是not accurate。 Windows 7“截取工具”获取correct dimensions。我怎么能这样做?
我的第一个想法是列举如下,但如果像你的状态,你肯定GetWindowRect
被返回的值不正确,请参阅解决方案进一步下跌。
“这有什么错GetSystemMetrics(SM_CXBORDER)
和GetSystemMetrics(SM_CYBORDER)
?
您正在使用的方法似乎做的很婉转地和,如果你可以调用GetWindowRect()
,我敢肯定,你可以调用GetSystemMetrics()
为好。
另外一个可能性是使用GetWindowRect
以获取窗口和GetClientRect
整个边框以获取客户端(非边境)地区的边界矩形。
这应该给你像(100,200),(1000,900)
和(112,227),(988,888)
分别,你可以计算出上边框为227-200
,底部为900-888
,留给112-100
,右为900-888
(27,12,12,12)。
解决方案:
调查的位变成了this。这是2006年的一个帖子,指出您可能无法从GetWindowsRect
获得正确的值。这个线程指出我这样说:
Vista下未与WINVER = 6链接的应用程序将在这里收到一组令人误解的值,这不包括“玻璃”像素的额外填充Vista Vista Aero适用于该窗口。即使在Aero Basic(没有玻璃)中也会出现这种情况,以保持尺寸一致性。解决方法(如果您不想设置WINVER = 6)似乎是动态绑定到dwmapi.dll并使用GetProcAddress()获取DwmGetWindowAttribute()函数,并使用DWMWA_EXTENDED_FRAME_BOUNDS参数调用它以请求真正的窗口框架尺寸。
所以基本上,使用类似(您可能需要使用ctypes的从Python中做到这一点):
RECT r;
HRESULT stat = DwmGetWindowAttribute (
hwnd,
DWMWA_EXTENDED_FRAME_BOUNDS,
&r,
sizeof(r));
而且应该给你正确的边框。
第一,调用GetClientRect以检索客户端矩形R1, 然后调用AdjustWindowRectEx根据R1来计算准确的边界。
GetWindowRect返回正确的值,但用于显式处理窗口。使用GetParent function得到父窗口的句柄,而GetWindowWRect返回给你的最大RECT或GetParent返回值为NULL。
OP已经*在这里讨论顶层窗口。 – BrendanMcK 2012-08-20 20:35:00
我知道这是一个有点老话题。但是它花费了大量的搜索时间,并且我通过ctypes痛苦地解决了paxdiablo的解决方案。只是想分享工作代码样本的wxPython:
try:
f = ctypes.windll.dwmapi.DwmGetWindowAttribute
except WindowsError:
f = None
if f: # Vista & 7 stuff
rect = ctypes.wintypes.RECT()
DWMWA_EXTENDED_FRAME_BOUNDS = 9
f(ctypes.wintypes.HWND(self.GetHandle()),
ctypes.wintypes.DWORD(DWMWA_EXTENDED_FRAME_BOUNDS),
ctypes.byref(rect),
ctypes.sizeof(rect)
)
size = (rect.right - rect.left, rect.bottom - rect.top)
else:
size = self.GetSize()
在Windows 7 GetWindowRect似乎不包括如果窗口创建右侧和底部窗框边缘(至少Aero主题据我所知),没有 WS_SIZEBOX风格(即,你想要一个不可调整大小的窗口)。
问题是,WS_SIZEBOX与WS_THICKFRAME相同,并且在Aero上,无论窗口是否可以调整大小,窗口都有厚框。但GetWindowRect函数认为不可调整大小的窗口更薄。
修复?您可以使用WS_SIZEBOX创建窗口,调用GetWindowRect,然后使用SetWindowLongPtr(GWL_STYLE,...)关闭WS_SIZEBOX,但这会在客户区域内创建一个丑陋的白色边框。
取而代之的是,保持WS_SIZEBOX启用,并在响应WM_GETMINMAXINFO消息时,简单地为MINMAXINFO结构中的ptMinTrackSize和ptMaxTraceSize返回相同的值。 这将使窗口不能调整大小,GetWindowRect将返回适当的数据。唯一的缺点是,当鼠标指针移到窗口框架上时,鼠标光标仍然会变成一个调整大小的光标,但它是目前为止的恶意中较小的一个。
那么,它返回1. 1不是该窗口上任何边界的宽度。我很确定我想要的那个窗口的值是8和30. – 2010-07-07 06:04:29
你怎样得到8和30?正确的外观框架似乎在底部具有与侧面相同的宽度。 – paxdiablo 2010-07-07 06:25:24
我也关心顶部。 – 2010-07-07 06:43:04