Как найти положение элемента управления/окна Win32 относительно родительского окна?

учитывая дескриптор окна Win32, мне нужно найти его положение относительно родительского окна.

Я знаю нескольких функций (например,GetWindowRect() и GetClientRect()), но ни один из них явно не возвращает нужные координаты.

Как мне это сделать?

3 ответов


решение использует силу GetWindowRect() и MapWindowPoints().

GetWindowRect() получает координаты окна относительно всей области экрана, которую вы видите на мониторе. Нам нужно преобразовать эти абсолютные координаты в относительные координаты нашей области главного окна. The MapWindowPoints() преобразование координат относительно одного окна относительно другого. Поэтому нам нужна "ручка" области экрана и ручка родительского окна контроль, координаты которого мы пытаемся найти. Экран - это " окно "в терминологии Windows, и он называется"Рабочий стол". Мы можем получить доступ к дескриптору Desktop с помощью константы HWND_DESKTOP определена в WinUser.h (включая Windows.h достаточно). И мы можем получить дескриптор нашего родительского окна, просто вызвав функцию Win32 GetParent(). Теперь у нас есть все параметры, необходимые для вызова .

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

MapWindowPoints() определяется as:

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

MapWindowPoints() преобразование координат относительно из hWndFrom to hWndTo. В нашем случае мы делаем преобразование с рабочего стола (HWND_DESKTOP) к нашему родительскому окну (GetParent(hWnd)). Следовательно, в результате RECT структура содержит относительные координаты нашего дочернего окна (hWnd) относительно родительского окна.


это решение, которое я использую либо для windows, либо для элементов управления (дочерние окна)

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

вот функция, которая принимает элементы обоих ответов во что-то полезное-особенно для перемещения / изменения координат управления.
Он принимает в качестве параметров интегральный идентификатор элемента управления из ресурса и дескриптор для его контейнера.
Следует также рассмотреть, является ли 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;
}