2013-08-03 10 views
23

Win32ウィンドウのハンドルを指定すると、その親ウィンドウに対する相対位置を見つける必要があります。親ウィンドウに対するWin32コントロール/ウィンドウの位置を見つけるにはどうすればよいですか?

私はいくつかの機能(例えば、GetWindowRect()GetClientRect())を知っていますが、それらのどれも明示的に目的の座標を返すものはありません。

どうすればよいですか?

答えて

34

この解決策は、合計出力をGetWindowRect()MapWindowPoints()としています。

GetWindowRect()は、モニタに表示される画面領域全体を基準にしたウィンドウの座標を取得します。これらの絶対座標をメインウィンドウ領域の相対座標に変換する必要があります。 MapWindowPoints()は、あるウィンドウに対して与えられた座標を別のウィンドウに対して相対的に変換します。だから私たちは、座標を見つけることを試みているコントロールの親ウィンドウのスクリーン領域とハンドルの "ハンドル"が必要です。画面はWindowsの用語では「ウィンドウ」であり、「デスクトップ」と呼ばれます。デスクトップのハンドルにはのWinUser.hで定義された定数(Windows.hで十分です)でアクセスできます。 Win32関数GetParent()を呼び出すだけで、親ウィンドウのハンドルを得ることができます。これで、MapWindowPoints()関数を呼び出すために必要なすべてのパラメータが得られました。

RECT YourClass::GetLocalCoordinates(HWND hWnd) const 
{ 
    RECT Rect; 
    GetWindowRect(hWnd, &Rect); 
    MapWindowPoints(HWND_DESKTOP, GetParent(hWnd), (LPPOINT) &Rect, 2); 
    return Rect; 
} 

MapWindowPoints()のように定義される:hWndTo比較的hWndFromから座標を変換

int MapWindowPoints(
    _In_  HWND hWndFrom, 
    _In_  HWND hWndTo, 
    _Inout_ LPPOINT lpPoints, 
    _In_  UINT cPoints 
); 

MapWindowPoints()。この例では、デスクトップ(HWND_DESKTOP)から親ウィンドウ(GetParent(hWnd))に変換します。したがって、結果のRECT構造体は、親ウィンドウを基準にした子ウィンドウ(hWnd)の相対座標を保持します。私は窓のためか、コントロールのいずれかを使用しています溶液(子ウィンドウ)

RECT rc; 
GetClientRect(hWnd,&rc); 
MapWindowPoints(hWnd,GetParent(hWnd),(LPPOINT)&rc,2); 
+1

今日、私はこの問題の解決策を見つけるのにかなりの時間をかけました。この問題については、インターネットやこのサイトでも、間違った情報や誤解を招くような情報がたくさんあります。 Win32がこの情報を収集する明示的な機能を持たないことは大きな悲劇であり、この単純な問題の解決のための良い説明とサンプルコードを見つけるのは非常に難しいこともひどいです。私はここで解決策を共有しています。これは、今後検索する他のユーザーを助けるためです。 – hkBattousai

+1

本当に、複数のモニターでこの作品は??? – Xearinox

+0

@ Xearinox私はここで死者を育てていることに気付いていますが...はい。複数のモニタでは、どちらがプライマリディスプレイであるかに応じて、プライマリディスプレイに対する座標を表すために、非常に負の値または正の値が返されます。 'SetCursorPos'を使って自分で試して、マウスカーソルがどこにあるのか確認してください。 – RectangleEquals

11


リソースからの統合コントロールIDとそのコンテナのハンドルをパラメータとして受け取ります。
SIZE_MINIMIZEDをリスニングして関数を呼び出す前に、ownerHwndが最小化されているかどうかも考慮する必要があります。

BOOL ProcCtrl(int ctrlID, HWND ownerHwnd) 
{ 
    RECT rcClient = {0};   
    HWND hwndCtrl = GetDlgItem(ownerHwnd, ctrlID); 
    if (hwndCtrl) 
    { 
    GetWindowRect(hwndCtrl, &rcClient); //get window rect of control relative to screen 
    MapWindowPoints(NULL, ownerHwnd, (LPPOINT)&rcClient,2); 

    // Set scaling parameters to suit in either of the following functions 
    //if (!MoveWindow(hwndCtrl, rcClient.left, rcClient.top, 
    //rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, TRUE)) 
    { 
     //Error; 
     //return FALSE; 
    } 
    //if (!SetWindowPos(hwndCtrl, NULL, (int)rcClient.left, (int)(rcClient.top), 
    //(int)(rcClient.right - rcClient.left), (int)(rcClient.bottom - rcClient.top), SWP_NOZORDER)) 
    { 
     //Error; 
     //return FALSE; 
    } 
    } 
    else 
    { 
     //hwndCtrl Error; 
     //return FALSE; 
    } 
    return TRUE; 
} 
+0

MapWindowPoints(hWnd、GetParent(hWnd)、LPPOINT)でなければならない&rc,1); –

+0

なぜそれが@Erdincであるのでしょうか?rectで2つの*点があります –

+0

2点で1オブジェクトを得ると思います –

0

はここで特に移動のため/制御座標をリサイズusable-何かに両方の回答の要素をとる関数ですさ

関連する問題