GetWindowRect在Windows 7上太小了

时间:2010-07-07 05:53:42

标签: python windows winapi pywin32

我想解决的实际问题是,我想自动找出窗口周围边距的大小。如果你能找到更好的方法,请一定要回答这个问题。

为此,我决定拍摄测试窗口的屏幕截图并测量边距。这很简单,因为我预计没有任何边缘会变成鲜艳的粉红色,但我承认这是一个黑客。我使用GetWindowRectpy)获取边界框,PIL获取屏幕截图并裁剪到边界框。问题是当裁剪正确运行时,边界框为not accurate。 Windows 7“Snipping Tool”获得correct dimensions。我怎么能这样做?

6 个答案:

答案 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)

答案 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。