我试图解决的实际问题是,我想自动找出窗口边缘的大小。 如果你能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()
DwmGetWindowAttribute
http://msdn.microsoft.com/en-us/library/aa969515%28VS.85%29.aspx
首先,调用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。