Указанный дескриптор окна Win32, мне нужно найти его положение относительно его родительского окна.
Я знаю несколько функций (например, GetWindowRect()
и GetClientRect()
), но ни один из они явно возвращают требуемые координаты.
Как это сделать?
Указанный дескриптор окна Win32, мне нужно найти его положение относительно его родительского окна.
Я знаю несколько функций (например, GetWindowRect()
и GetClientRect()
), но ни один из они явно возвращают требуемые координаты.
Как это сделать?
Решение использует объединенную мощность GetWindowRect()
и MapWindowPoints()
.
GetWindowRect()
извлекает координаты окна относительно всей области экрана, которую вы видите на своем мониторе. Нам нужно преобразовать эти абсолютные координаты в относительные координаты нашей основной области окна. MapWindowPoints()
преобразует координаты, заданные относительно одного окна, относительно другого. Поэтому нам нужен "дескриптор" области экрана и дескриптор родительского окна элемента управления, в котором мы пытаемся найти координаты. Экран - это "окно" в терминологии Windows, и он называется "Рабочий стол". Мы можем получить доступ к дескриптору Desktop постоянной константой 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()
преобразуют координаты относительно от hWndFrom
до hWndTo
. В нашем случае мы делаем преобразование из рабочего стола (HWND_DESKTOP
) в родительское окно (GetParent(hWnd)
). Поэтому результирующая структура RECT
содержит относительные координаты нашего дочернего окна (hWnd
) относительно его родительского окна.
Это решение, которое я использую либо для окон, либо для элементов управления (дочерние окна)
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;
}