代码之家  ›  专栏  ›  技术社区  ›  Devin Jeanpierre

在Windows 7上GetWindowRect太小

  •  12
  • Devin Jeanpierre  · 技术社区  · 15 年前

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

    为了做到这一点,我决定截取一个测试窗口的屏幕截图并测量边缘。这很简单,正如我所期望的,没有任何利润会是亮粉色的,但我承认这是一个黑客行为。我用 GetWindowRect ( py )获取边界框,以及 PIL 获取屏幕截图并裁剪到边界框。问题是,当裁剪操作正确时,边界框是 not accurate . Windows7“截图工具”获取 correct dimensions . 我该怎么做呢?

    6 回复  |  直到 8 年前
        1
  •  18
  •   Blorgbeard    8 年前

    我的第一个想法列在下面,但如果,如你所说,你确定 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-88 (27,12,12,12)。


    决议:

    有点调查 this . 它是2006年的一个线程,说明您可能无法从 GetWindowsRect . 指向我这一点的线索表明:

    vista下未链接winver=6的应用程序将在此处收到一组误导性的值,这些值不会解释vista aero应用于窗口的“玻璃”像素的额外填充。这似乎发生在航空基本(没有玻璃)保持大小一致性。解决方法(如果不想设置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));
    

    这会给你一个正确的边界矩形。

        2
  •  3
  •   Fenikso    12 年前

    我知道这是一个有点老套的话题。但是,我花了相当多的时间搜索,我自己也经历了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()
    
        3
  •  1
  •   Windows programmer    15 年前
        4
  •  1
  •   JGShining    15 年前

    首先,调用getclientract检索客户机矩形r1, 然后调用adjustwindowrectex根据r1计算精确的界限。

        5
  •  1
  •   Ray Gardener    11 年前

    Windows7上的GetWindowRect似乎不包括右下窗口框架边缘(至少使用Aero主题Afaik)。 如果 窗口已创建 没有 WS-SizeBox样式(即,您需要一个不可调整大小的窗口)。

    问题是,WS-SizeBox与WS-ThickFrame相同,在Aero上,无论是否可以调整大小,Windows都具有ThickFrame。但是getWindowRect函数认为不可调整大小的窗口更薄。

    修复?您可以使用ws撘sizebox创建窗口,调用getwindowrect,然后使用setwindowlongptr(gwl_-style,…)关闭ws撘sizebox,但这将在客户端区域内创建一个难看的白色边框。

    相反,保持启用ws_SizeBox,并在响应wm_GetMinMaxInfo消息时,只返回minMaxInfo结构中ptMinTrackSize和ptMaxTraceSize的相同值。 这将使窗口不可调整大小,GetWindowRect将返回正确的数据。唯一的缺点是,当鼠标指针移到窗口框架上时,鼠标光标仍将变为调整大小的光标,但这是迄今为止较轻的缺点。

        6
  •  0
  •   Survarium    13 年前

    GetWindowRect返回正确的值,但用于窗口的显式句柄。使用 GetParent function 若要获取父窗口的句柄,而GetWindowRect返回的最大Rect或GetParent返回值为空。