我试图解决的实际问题是自动找到窗口周围边距的大小。如果您有更好的方法,请务必回答,而不是回答这个。
为了做到这一点,我决定对测试窗口进行截屏并测量边距。这很简单,因为我预计没有边距会是亮粉色的,但我承认这是一个hack。我使用GetWindowRect (py)来获取边框框架,然后使用PIL 来截取屏幕截图并裁剪到边框框架。问题在于,虽然裁剪操作是正确的,但边框框架是不准确的。Windows 7 的“剪切工具”获取了正确的尺寸。我应该如何做到这一点?
我试图解决的实际问题是自动找到窗口周围边距的大小。如果您有更好的方法,请务必回答,而不是回答这个。
为了做到这一点,我决定对测试窗口进行截屏并测量边距。这很简单,因为我预计没有边距会是亮粉色的,但我承认这是一个hack。我使用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)。
解决方法:
一些调查结果显示,在这个线程中提到,可能无法从 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
GetWindowRect返回正确的值,但是需要显式指定窗口句柄。使用GetParent函数获取父窗口的句柄,而GetWindowRect将为您返回最大的RECT或者GetParent返回值为空。