我想解决的实际问题是,我想自动找出窗口周围边距的大小。如果你能找到更好的方法,请一定要回答这个问题。
为此,我决定拍摄测试窗口的屏幕截图并测量边距。这很简单,因为我预计没有任何边缘会变成鲜艳的粉红色,但我承认这是一个黑客。我使用GetWindowRect(py)获取边界框,PIL获取屏幕截图并裁剪到边界框。问题是当裁剪正确运行时,边界框为not accurate。 Windows 7“Snipping Tool”获得correct dimensions。我怎么能这样做?
答案 0 :(得分:18)
我的第一个想法如下所示,但如果您说明GetWindowRect
返回的值不正确,请参阅 RESOLUTION 。
“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 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));
这应该会给你正确的边界矩形。
答案 1 :(得分:3)
我知道这是一个有点老话题。但它花了很多时间进行搜索,我自己也经历了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()
答案 2 :(得分:1)
DwmGetWindowAttribute
http://msdn.microsoft.com/en-us/library/aa969515%28VS.85%29.aspx
答案 3 :(得分:1)
首先,调用GetClientRect来检索客户端矩形R1, 然后调用AdjustWindowRectEx根据R1计算准确的边界。
答案 4 :(得分:1)
Windows 7上的GetWindowRect似乎不包括右侧和底部窗口边框(至少Aero主题为afaik),如果窗口是而不是 WS_SIZEBOX风格(即你想要一个不大的窗口)。
问题是,WS_SIZEBOX与WS_THICKFRAME相同,而在Aero上,无论是否可以调整大小,Windows都会显示粗框。但GetWindowRect函数认为不可调整大小的窗口更薄。
修复?您可以使用WS_SIZEBOX创建窗口,调用GetWindowRect,然后使用SetWindowLongPtr(GWL_STYLE,...)关闭WS_SIZEBOX,但这会在客户区域内创建一个丑陋的白色边框。
相反,保持启用WS_SIZEBOX,并在响应WM_GETMINMAXINFO消息时,仅在MINMAXINFO结构中为ptMinTrackSize和ptMaxTraceSize返回相同的值。 这将使窗口无法调整大小,GetWindowRect将返回正确的数据。唯一的缺点是,当鼠标指针越过窗口框架时,鼠标光标仍然会变为调整大小的光标,但到目前为止,这只是邪恶中较小的一个。
答案 5 :(得分:0)
GetWindowRect返回正确的值,但是对于窗口的显式句柄。使用 GetParent function 来获取父窗口的句柄,而GetWindoWRect返回最大RECT或GetParent返回值为NULL。