Ширина и высота границы окна в Win32 - как мне ее получить?
::GetSystemMetrics (SM_CYBORDER)
... возвращается с 1, и я знаю, что строка заголовка выше, чем ОДИН пиксель:/
Я также пробовал:
RECT r;
r.left = r.top = 0; r.right = r.bottom = 400;
::AdjustWindowRect (& r, WS_OVERLAPPED, FALSE);
_bdW = (uword)(r.right - r.left - 400);
_bdH = (uword)(r.bottom - r.top - 400);
Но граница w, h вернулась как 0.
В моем обработчике WM_SIZE мне нужно убедиться, что высота окна изменяется в
"шаги", поэтому, например, в окно может входить вся новая строка текста
без дробного частичного линейного пространства внизу.
Но:: MoveWindow нуждается в размерах с добавлением пограничного пространства.
Кто-то, должно быть, сделал это раньше...
Спасибо за любую помощь:)
Ответы
Ответ 1
GetWindowRect и GetClientRect можно использовать вычисления размер всех границ окна.
В Suite101 есть статья о изменении размера окна и поддерживающей клиентской области с размером значка.
Вот пример кода:
void ClientResize(HWND hWnd, int nWidth, int nHeight)
{
RECT rcClient, rcWind;
POINT ptDiff;
GetClientRect(hWnd, &rcClient);
GetWindowRect(hWnd, &rcWind);
ptDiff.x = (rcWind.right - rcWind.left) - rcClient.right;
ptDiff.y = (rcWind.bottom - rcWind.top) - rcClient.bottom;
MoveWindow(hWnd,rcWind.left, rcWind.top, nWidth + ptDiff.x, nHeight + ptDiff.y, TRUE);
}
Ответ 2
int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
Фактически, приведенный выше результат может быть равен:
GetClientRect(hWnd, &rcClient);
GetWindowRect(hWnd, &rcWind);
int border_thickness = ((rcWind.right - rcWind.left) - rcClient.right) / 2;
но GetSystemMetrics(SM_CXSIZEFRAME)
проще в использовании.
Ответ 3
Я думаю, что вы ищете SM_CYCAPTION
- это высота строки заголовка. SM_CYBORDER
- высота горизонтальных краев окна.
Ответ 4
Метод, предложенный stukelly, будет работать, если окно не будет минимизировано или не будет полностью запущено. Альтернативный подход, который даст вам размер границы в этих условиях, заключается в использовании функции AdjustWindowRectEx
. Вот пример:
CSize GetBorderSize(const CWnd& window)
{
// Determine the border size by asking windows to calculate the window rect
// required for a client rect with a width and height of 0
CRect rect;
AdjustWindowRectEx(&rect, window.GetStyle(), FALSE, window.GetExStyle());
return rect.Size();
}
В зависимости от приложения может потребоваться совместить этот подход с stukelly, если необходим текущий видимый размер границы:
CSize GetBorderSize(const CWnd& window)
{
if (window.IsZoomed())
{
// The total border size is found by subtracting the size of the client rect
// from the size of the window rect. Note that when the window is zoomed, the
// borders are hidden, but the title bar is not.
CRect wndRect, clientRect;
window.GetWindowRect(&wndRect);
window.GetClientRect(&clientRect);
return wndRect.Size() - clientRect.Size();
}
else
{
// Determine the border size by asking windows to calculate the window rect
// required for a client rect with a width and height of 0. This method will
// work before the window is fully initialized and when the window is minimized.
CRect rect;
AdjustWindowRectEx(&rect, window.GetStyle(), FALSE, window.GetExStyle());
return rect.Size();
}
}
Ответ 5
Head Geek дает подробный ответ: используйте GetSystemMetrics для добавления надписей и битов границы. Вы также можете сделать разницу в ширине/высоте между GetWindowRect и GetClientRect. Это даст вам общее количество всех титров/границ/и т.д.
Ответ 6
У вас есть другое решение... Вы можете предварительно рассчитать границу, вызвав специальную функцию в сообщениях WM_CREATE и WM_INITDIALOG. И обновите значения при изменении стиля окна или когда меню разделено на две строки.
RECT cRect, wRect, oRect;
GetWindowRect(hWnd, &wRect);
GetClientRect(hWnd, &cRect);
MapWindowPoints(hWnd, NULL, (LPPOINT)&cRect, 2);
oRect.left = cRect.left - wRect.left;
oRect.top = cRect.top - wRect.top;
oRect.right = wRect.right - cRect.right;
oRect.bottom = wRect.bottom - cRect.bottom;