如何找到Win32控件/窗口相对于其父窗口的位置?

时间:2013-08-03 16:32:15

标签: winapi window position relative win32gui

给定Win32窗口的句柄,我需要找到它相对于其父窗口的位置。

我知道几个函数(例如; GetWindowRect()GetClientRect()),但它们都没有明确返回所需的坐标。

我该怎么做?

5 个答案:

答案 0 :(得分:36)

解决方案正在使用GetWindowRect()MapWindowPoints()的强大功能。

GetWindowRect()检索窗口相对于监视器上显示的整个屏幕区域的坐标。我们需要将这些绝对坐标转换为主窗口区域的相对坐标。 MapWindowPoints()将相对于一个窗口给出的坐标转换为相对于另一个窗口的坐标。所以我们需要一个屏幕区域的“句柄”和我们试图找到坐标的控件的父窗口的句柄。屏幕是Windows术语中的“窗口”,它被称为“桌面”。我们可以通过HWND_DESKTOP中定义的常量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()定义为:

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

MapWindowPoints()将坐标相对转换为hWndFromhWndTo。在我们的例子中,我们进行从桌面(HWND_DESKTOP)到父窗口(GetParent(hWnd))的转换。因此,生成的RECT结构保存了子窗口(hWnd)相对于其父窗口的相对坐标。

答案 1 :(得分:11)

这是我用于windows或控件(子窗口)的解决方案

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

答案 2 :(得分:0)

我知道它已经被回答过了,但是更容易获得子窗口在屏幕坐标中的矩形,获得其位置(POINT ptCWPos = {rectCW.left, rectCW.top};)并使用ScreenToClient()函数,这将改变屏幕坐标点到窗口的客户端坐标点:

PS:我知道看起来好像很多代码,但是大多数代码都摆在rect位置上。在大多数情况下,实际上需要一个直肠位置,而不是整个直肠。


HWND hwndCW, hwndPW; // the child window hwnd
                     // and the parent window hwnd
RECT rectCW;
GetWindowRect(hwndCW, &rectCW); // child window rect in screen coordinates
POINT ptCWPos = { rectCW.left, rectCW.top };
ScreenToClient(hwndPW, &ptCWPos); // transforming the child window pos
                                  // from screen space to parent window space
LONG iWidth, iHeight;
iWidth = rectCW.right - rectCW.left;
iHeight = rectCW.bottom - rectCW.top;

rectCW.left = ptCWPos.x;
rectCW.top = ptCWPos.y;
rectCW.right = rectCW.left + iWidth;
rectCW.bottom = rectCW.right + iHeight; // child window rect in parent window space

答案 3 :(得分:0)

更简单

BOOL CAuxFormView::OnInitDialog()
{
    // run the default
    CDialog::OnInitDialog();
    // define a rectangular
    CRect rc1;
    // get area of the control to the screen coordinates
    m_Viewer_Ctrl.GetWindowRect(rc1);
    // transform the screen coordinates relevant to the Dialog coordinates
    ScreenToClient(rc1);
    // move and refresh the control to the new area
    m_Viewer_Ctrl.MoveWindow(rc1);

}

答案 4 :(得分:-1)

这是一个将两个答案的元素都用到可用的东西的功能 - 特别是用于移动/调整控制坐标。 它接受来自资源的整体控制ID作为参数,以及其容器的句柄 在调用该函数之前,还应考虑ownerHwnd是否通过在SIZE_MINIMIZED中监听WM_SIZE来最小化。

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;
}