As you have noticed, SetWindowPos()
resizes the entire window as a whole. Instead, you are wanting a specific size for just the client area 1 of the window, letting the OS handle the rest of the window surrounding the client area.
1: see About Windows on MSDN for an explanation of the different components of a window.
The Win32 API has functions for exactly this situation:
AdjustWindowRect()
and AdjustWindowRectEx()
Calculates the required size of the window rectangle, based on the desired size of the client rectangle. The window rectangle can then be passed to the CreateWindowEx function to create a window whose client area is the desired size.
If your app is DPI-aware, there is also AdjustWindowRectExForDpi()
, too.
So, you give them the size of the client area that you want, and also specify the window styles (which affect the various borders, margins, spacing, etc surrounding the client area, thus affecting the window's width and height), and whether a menu is present (which affects the positioning of the client area relative to the title bar, and thus affecting the window's height), and if needed the DPI scaling.
They will give you back the window size that is needed to achieve the specified client area size. You can then resize the window to that adjusted size.
For example:
RECT r;
r.left = 0;
r.top = 0;
r.right = 400;
r.bottom = 400;
DWORD dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
DWORD dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
AdjustWindowRectEx(&r, dwStyle, TRUE, dwExStyle);
SetWindowPos(hWnd, NULL, 0, 0, r.right - r.left, r.bottom - r.top, SWP_NOMOVE | SWP_NOZORDER);