2010-07-07 21 views
12

我試圖解決的實際問題是,我想自動找出窗口邊緣的大小。如果你能找到更好的辦法,請盡一切辦法回答這個問題,而不是這個。在Windows 7上GetWindowRect太小

爲此,我決定截取測試窗口並測量邊距。這很簡單,因爲我預計沒有利潤率會變成明亮的粉紅色,但我承認這是一種黑客行爲。我使用GetWindowRectpy)獲取邊界框,並使用PIL獲取屏幕截圖並剪裁到邊界框。問題是,當作物正常運行時,邊界框是not accurate。 Windows 7「截取工具」獲取correct dimensions。我怎麼能這樣做?

回答

16

我的第一個想法是列舉如下,但如果像你的狀態,你肯定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)。


解決方案:

調查的位變成了this。這是2006年的一個帖子,指出您可能無法從GetWindowsRect獲得正確的值。這個線程指出我這樣說:

Vista下未與WINVER = 6鏈接的應用程序將在這裏收到一組令人誤解的值,這不包括「玻璃」像素的額外填充Vista 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)); 

而且應該給你正確的邊框。

+0

那麼,它返回1. 1不是該窗口上任何邊界的寬度。我很確定我想要的那個窗口的值是8和30. – 2010-07-07 06:04:29

+0

你怎樣得到8和30?正確的外觀框架似乎在底部具有與側面相同的寬度。 – paxdiablo 2010-07-07 06:25:24

+0

我也關心頂部。 – 2010-07-07 06:43:04

1

第一,調用GetClientRect以檢索客戶端矩形R1, 然後調用AdjustWindowRectEx根據R1來計算準確的邊界。

0

GetWindowRect返回正確的值,但用於顯式處理窗口。使用GetParent function得到父窗口的句柄,而GetWindowWRect返回給你的最大RECT或GetParent返回值爲NULL。

+3

OP已經*在這裏討論頂層窗口。 – BrendanMcK 2012-08-20 20:35:00

3

我知道這是一個有點老話題。但是它花費了大量的搜索時間,並且我通過ctypes痛苦地解決了paxdiablo的解決方案。只是想分享工作代碼樣本的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() 
1

在Windows 7 GetWindowRect似乎不包括如果窗口創建右側和底部窗框邊緣(至少Aero主題據我所知),沒有 WS_SIZEBOX風格(即,你想要一個不可調整大小的窗口)。

問題是,WS_SIZEBOX與WS_THICKFRAME相同,並且在Aero上,無論窗口是否可以調整大小,窗口都有厚框。但GetWindowRect函數認爲不可調整大小的窗口更薄。

修復?您可以使用WS_SIZEBOX創建窗口,調用GetWindowRect,然後使用SetWindowLongPtr(GWL_STYLE,...)關閉WS_SIZEBOX,但這會在客戶區域內創建一個醜陋的白色邊框。

取而代之的是,保持WS_SIZEBOX啓用,並在響應WM_GETMINMAXINFO消息時,簡單地爲MINMAXINFO結構中的ptMinTrackSize和ptMaxTraceSize返回相同的值。 這將使窗口不能調整大小,GetWindowRect將返回適當的數據。唯一的缺點是,當鼠標指針移到窗口框架上時,鼠標光標仍然會變成一個調整大小的光標,但它是目前爲止的惡意中較小的一個。