在Windows 7上GetWindowRect太小

我试图解决的实际问题是,我想自动找出窗口边缘的大小。 如果你能find更好的办法,请用一切办法来回答,而不是这个。

为此,我决定截取testing窗口并测量边距。 这很简单,因为我认为没有利润率会是明亮的粉红色,但我承认这是一个黑客。 我使用GetWindowRect ( py )来获取边界框, PIL抓取屏幕截图并剪裁到边界框。 问题是,当作物正常运行时,边界框不准确 。 Windows 7“剪切工具”获得正确的尺寸 。 我怎么能这样做?

我的第一个想法列在下面,但是,如果您确定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)。


解析度:

有点调查了这个 。 这是2006年的一个线程,指出你可能无法从GetWindowsRect获得正确的值。 指出我的这个线程指出:

Vista下没有与WINVER = 6链接的应用程序将在这里收到一组令人误解的值,这些值并不包含“玻璃”像素的额外填充。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)); 

这应该给你正确的边界矩形。

我知道这是一个老话题。 但是花费了很多搜索的时间,我经历了ctypes的痛苦,让paxdiablo的解决方案在Python中工作。 只是想分享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() 

首先,调用GetClientRect来检索客户端矩形R1,然后调用AdjustWindowRectEx根据R1计算精确边界。

如果窗口创建时没有 WS_SIZEBOX风格(即,您想要一个不可调整大小的窗口),Windows 7上的GetWindowRect似乎不包括右边和底部窗口边框(至少在Aero主题afaik中)。

问题是,WS_SIZEBOX和WS_THICKFRAME是一样的,在Aero上,窗口是否可以调整大小, 但是GetWindowRect函数认为不可调整大小的窗口更薄。

修复? 您可以使用WS_SIZEBOX创建窗口,调用GetWindowRect,然后使用SetWindowLongPtr(GWL_STYLE,…)关闭WS_SIZEBOX,但这将在客户区域内创建一个丑陋的白色边框。

相反,将WS_SIZEBOX设置为启用状态,并在响应WM_GETMINMAXINFO消息时简单地返回MINMAXINFO结构中的ptMinTrackSize和ptMaxTraceSize的相同值。 这将使窗口不能调整大小,GetWindowRect将返回适当的数据。 唯一的缺点是,当鼠标指针移到窗口框架上时,鼠标光标仍然会变成一个调整大小的光标,但是到目前为止,它是较小的。

GetWindowRect返回正确的值,但为了显式处理窗口。 使用GetParent函数获取父窗口的句柄,而GetWindowWRect返回给你的最大RECT或GetParent返回值为NULL。