Window Border Width and Height in Win32 - How to Get It

window border width and height in Win32 - how do I get it?

The GetWindowRect and GetClientRect functions can be used calculate the size of all the window borders.

Suite101 has a article on resizing a window and the keeping client area at a know size.

Here is their sample code:

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

How do we get the border size of a window?

On windows you can use GetWindowRect and GetClientRect

RECT windowRect;
GetWindowRect(hwnd, &windowRect);

RECT clientRect;
GetClientRect(hwnd, &clientRect);

int borderWidth = ((windowRect.right - windowRect.left) - (clientRect.right -clientRect.left))/2;

Though GetClientRect should give you the inner width of the window and that should be enough for you.

int innerWidth = clientRect.right - clientRect.left;

How to adjust window border size

Maybe you can use MoveWindow to resize the window, and then draw the border yourself, like this,

Sample Image

Draw a borderless window first:

HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
100, 100, 800, 600, nullptr, nullptr, hInstance, nullptr);
LONG lStyle = GetWindowLong(hWnd, GWL_STYLE);
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
SetWindowLong(hWnd, GWL_STYLE, lStyle);

Then handle the window border in the WM_LBUTTONDOWN message:

int num = 0;
case WM_LBUTTONDOWN:
{
RECT rcWind;
HDC dc = GetDC(hWnd);
GetWindowRect(hWnd, &rcWind);
if (num >= 0)
{
num--;
RECT rcClient;
MoveWindow(hWnd, rcWind.left - 4, rcWind.top - 4, 8 + rcWind.right - rcWind.left, 8 + rcWind.bottom - rcWind.top, TRUE);
GetClientRect(hWnd, &rcClient);
HPEN hPen = CreatePen(PS_SOLID, 4, RGB(255, 128, 1));
HGDIOBJ hOldPen = SelectObject(dc, hPen);
Rectangle(dc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
DeleteObject(hPen);
}
else if (num < 0)
{
MoveWindow(hWnd, rcWind.left + 4, rcWind.top + 4, rcWind.right - rcWind.left - 8, rcWind.bottom - rcWind.top - 8, TRUE);
num++;
}
}
break;

How to change the border size of a single window?

Unless you do it by owner-drawn your only options are changing the border type between dialog, fixed single and none. They are of different thicknesses and looks and behaviors so not a great choice. Making your own is definitely the only way to go.

AN easy way to "create your own border" coould actually be to do Windows Skinning

GetWindowRect returns a size including invisible borders

Windows 10 has thin invisible borders on left, right, and bottom, it is used to grip the mouse for resizing. The borders might look like this: 7,0,7,7 (left, top, right, bottom)

When you call SetWindowPos to put the window at this coordinates:

0, 0, 1280, 1024

The window will pick those exact coordinates, and GetWindowRect will return the same coordinates. But visually, the window appears to be here:

7, 0, 1273, 1017

You can fool the window and tell it to go here instead:

-7, 0, 1287, 1031

To do that, we get Windows 10 border thickness:

RECT rect, frame;
GetWindowRect(hwnd, &rect);
DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frame, sizeof(RECT));

//rect should be `0, 0, 1280, 1024`
//frame should be `7, 0, 1273, 1017`

RECT border;
border.left = frame.left - rect.left;
border.top = frame.top - rect.top;
border.right = rect.right - frame.right;
border.bottom = rect.bottom - frame.bottom;

//border should be `7, 0, 7, 7`

Then offset the rectangle like so:

rect.left -= border.left;
rect.top -= border.top;
rect.right += border.left + border.right;
rect.bottom += border.top + border.bottom;

//new rect should be `-7, 0, 1287, 1031`

Unless there is a simpler solution!

Get the size of non-client area of a themed Edit Control

How do you get the width of the border (non-client) of a themed Edit
control in Windows XP and later versions?

The following works for all controls, whether they are themed or not. It doesn't even need the theme API.

  1. Call GetClientRect() to get the size of the client area.
  2. Call ClientToScreen() to transform client rect to screen coordinates.
  3. Call GetWindowRect() to get the rectangle of the control including NC area, in screen coordinates.
  4. Calculate difference between client rect and window rect coordinates to get size of border (e. g. leftBorderWidth = clientRect.left - windowRect.left).

Edit:

Interestingly, the Wine source theme_edit.c doesn't use GetThemeMetric() at all. Instead they call GetSystemMetrics() with SM_CXEDGE and SM_CYEDGE.

On my systems (Windows 7 and Windows 10), this returns the correct value of 2.

Windows: Getting a window title bar's height

Assuming that you don't have menu bar, you can map points from client coordinate system to screen one

RECT wrect;
GetWindowRect( hwnd, &wrect );
RECT crect;
GetClientRect( hwnd, &crect );
POINT lefttop = { crect.left, crect.top }; // Practicaly both are 0
ClientToScreen( hwnd, &lefttop );
POINT rightbottom = { crect.right, crect.bottom };
ClientToScreen( hwnd, &rightbottom );

int left_border = lefttop.x - wrect.left; // Windows 10: includes transparent part
int right_border = wrect.right - rightbottom.x; // As above
int bottom_border = wrect.bottom - rightbottom.y; // As above
int top_border_with_title_bar = lefttop.y - wrect.top; // There is no transparent part

Got 8, 8, 8 and 31 pixels (96DPI aka 100% scaling setting)

You should also take into account DPI awareness mode. Especially GetSystemMetrics is tricky because it remembers state for System DPI when your application was launched.

Get exact window region size - CreateWindow window size isn't correct size of window

I use this method and now it works:

if ( IsWindow( hwnd ) )
{

DWORD dwStyle = GetWindowLongPtr( hwnd, GWL_STYLE ) ;
DWORD dwExStyle = GetWindowLongPtr( hwnd, GWL_EXSTYLE ) ;
HMENU menu = GetMenu( hwnd ) ;

RECT rc = { 0, 0, width, height } ;

AdjustWindowRectEx( &rc, dwStyle, menu ? TRUE : FALSE, dwExStyle );

SetWindowPos( hwnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOMOVE ) ;

}


Related Topics



Leave a reply



Submit