14

私が解決しようとしている実際の問題は、窓の周りの余白のサイズを自動的に見つけたいということです。より良い方法を見つけることができたら、これの代わりに必ず答えてください。

これを行うために、テストウィンドウのスクリーンショットを撮り、マージンを測定することにしました。余白が明るいピンクになることはないと思うので、これは十分に単純ですが、それはハックだと認めます。GetWindowRectpy)を使用してバウンディングボックスを取得し、 PILを使用してスクリーンショットを取得してバウンディングボックスにトリミングします。問題は、クロップが正しく動作しているのに、バウンディングボックスが正確でないことです。Windows7の「SnippingTool」は正しいサイズを取得します。どうすれば同じことができますか?

4

6 に答える 6

19

私の最初の考えを以下にリストしましたが、あなたが述べたように、それGetWindowRectが間違った値を返していることが確実な場合は、さらに下の解決策を参照してください。


GetSystemMetrics(SM_CXBORDER)「との何が問題なのGetSystemMetrics(SM_CYBORDER)ですか?

あなたが使用している方法は、それを行うための非常に回りくどい方法のようです. を呼び出すことができれば、同様GetWindowRect()に呼び出すことができると確信GetSystemMetrics()しています.

もう 1 つの可能性は、 を使用GetWindowRectして、ウィンドウの境界四角形全体をGetClientRect取得し、クライアント (非境界) 領域の境界四角形を取得することです。

これにより、 とそれぞれのようなもの得られ、上部の境界線を、下部を、左を、右を(27,12,12,12) として計算できます。(100,200),(1000,900)(112,227),(988,888)227-200900-888112-100900-888


解像度:

少し調査すると、これが判明します。から正しい値を取得できない可能性があると述べている 2006 年のスレッドですGetWindowsRect。これを指摘したスレッドは次のように述べています。

WINVER=6 でリンクされていない Vista の下のアプリは、Vista Aero がウィンドウに適用する「ガラス」ピクセルの余分なパディングを考慮していない、誤解を招く一連の値をここで受け取ります。これは、サイズの一貫性を維持するために、Aero Basic (Glass なし) でも発生するようです。回避策 (WINVER=6 を設定したくない場合) は、dwmapi.dll に動的にバインドし、GetProcAddress() を使用して DwmGetWindowAttribute() 関数を取得し、DWMWA_EXTENDED_FRAME_BOUNDS 引数を指定して呼び出して、正規のウィンドウを要求するようです。フレーム寸法。

したがって、基本的には、次のようなものを使用します (Python からこれを行うには ctypes を使用する必要がある場合があります):

RECT r;
HRESULT stat = DwmGetWindowAttribute (
    hwnd,
    DWMWA_EXTENDED_FRAME_BOUNDS,
    &r,
    sizeof(r));

これにより、正しい境界矩形が得られます。

于 2010-07-07T06:00:27.593 に答える
4

少し古いトピックであることは知っています。しかし、かなりの検索が必要で、paxdiablo のソリューションを Python で動作させるために、自分で ctypes の苦労を経験しました。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()
于 2012-11-19T18:28:39.687 に答える
2

Windows 7 の GetWindowRect は、ウィンドウがWS_SIZEBOX スタイルなしで作成された場合 (つまり、サイズ変更できないウィンドウが必要な場合)、ウィンドウ フレームの右端と下端を (少​​なくとも Aero テーマでは) 含まないように見えます。

問題は、WS_SIZEBOX が WS_THICKFRAME と同じであり、Aero では、ウィンドウのサイズを変更できるかどうかに関係なく、ウィンドウにシックフレームがあることです。しかし、GetWindowRect 関数は、サイズ変更できないウィンドウはより薄いと考えます。

修正?WS_SIZEBOX でウィンドウを作成し、GetWindowRect を呼び出し、次に SetWindowLongPtr(GWL_STYLE, ...) を使用して WS_SIZEBOX をオフにすることができますが、これによりクライアント領域内に醜い白い境界線が作成されます。

代わりに、WS_SIZEBOX を有効のままにして、WM_GETMINMAXINFO メッセージに応答するときに MINMAXINFO 構造体の ptMinTrackSize と ptMaxTraceSize に同じ値を返すだけです。これにより、ウィンドウのサイズを変更できなくなり、GetWindowRect は適切なデータを返します。唯一の欠点は、マウス ポインターがウィンドウ フレーム上に移動すると、マウス カーソルがサイズ変更カーソルに変わることですが、これまでのところ悪さはそれほど大きくありません。

于 2013-11-17T05:48:41.843 に答える
1

DwmGetWindowAttribute

http://msdn.microsoft.com/en-us/library/aa969515%28VS.85%29.aspx

于 2010-07-07T06:11:46.240 に答える
1

まず、GetClientRect を呼び出してクライアントの四角形 R1 を取得し、次に AdjustWindowRectEx を呼び出して、R1 に従って正確な境界を計算します。

于 2010-07-07T07:54:08.790 に答える
0

GetWindowRectは正しい値を返しますが、ウィンドウへの明示的なハンドル用です。GetParent関数を使用して親ウィンドウのハンドルを取得しますが、GetWindoWRectは最大のRECTを返すか、GetParentの戻り値はNULLです。

于 2012-08-20T06:05:57.110 に答える