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

我是研究僧i 提交于 2019-12-05 13:56:08

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

}

Just like @Deukalion, I inadvertently put the desired client area size into the ::CreateWindow() call, and while drawing a grid, I found myself short of pixels. I took the same approach of investigating the pixel size of a screenshot of my application. I could understand that the window's borders and title bar take away some room from the client area - but the frustrating thing is that under Windows 10, not even the total application window has the requested size!

I suspect that ::CreateWindow() calculates a smaller client area by subtracting a hardcoded amount of pixels in width and height, and then builds the window border and title bar around that. That hardcoded number is no longer correct with the ultra-thin stark window theme of Windows 10. It's ridiculous - there's really nothing on the screen of the size that was requested in ::CreateWindow() !

I followed the advice of @PeterRuderman to use the ::AdjustWindowRect() call :

RECT rect;
rect.left = rect.top = 0;
rect.right = clientWidth;
rect.bottom = clientHeight;
::AdjustWindowRect(&rect, wflags, false);
HWND hWindow = ::CreateWindow(wcName, title, wflags, 0, 0,
  rect.right - rect.left, rect.bottom - rect.top, 0, 0, hInstance, 0);
  • As stated on https://msdn.microsoft.com/en-us/library/windows/desktop/dd162897.aspx the RECT struct considers the right and bottom fields as outside the intended rectangle.
  • It would have been nice if ::AdjustWindowRect() would have left the given origin coordinates (0,0) intact, so that right and bottom could be directly filled into the ::CreateWindow() call. But to my surprise, the left and bottom fields turned negative.
Peter Ruderman

I still don't think you've provided enough info to solve your problem, but here's a complete program that does (basically) what you want. You can compare it to your own to see where you're going wrong.

#include <Windows.h>

LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch( uMsg ) {
    case WM_CLOSE:
        PostQuitMessage( 0 );
        break;

    case WM_PAINT:
        {
            RECT clientArea;
            GetClientRect( hwnd, &clientArea );

            PAINTSTRUCT ps;
            BeginPaint( hwnd, &ps );

            HBRUSH brush = (HBRUSH)GetStockObject( BLACK_BRUSH );

            RECT topLeft = clientArea;
            topLeft.right /= 2;
            topLeft.bottom /= 2;

            RECT bottomRight = clientArea;
            bottomRight.left = bottomRight.right / 2;
            bottomRight.top = bottomRight.bottom / 2;

            FillRect( ps.hdc, &topLeft, brush );
            FillRect( ps.hdc, &bottomRight, brush );

            EndPaint( hwnd, &ps );
        }

        return 0;
    }

    return DefWindowProc( hwnd, uMsg, wParam, lParam );
}

int CALLBACK WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    // Error checking omitted for brevity.
    WNDCLASSEX wc = { 0 };

    wc.cbSize = sizeof( wc );
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = L"testclass";

    ATOM classAtom = RegisterClassEx( &wc );

    HWND window = CreateWindow( L"testclass", L"Test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 480, 240, NULL, NULL, hInstance, NULL );

    MSG msg;

    while( GetMessage( &msg, NULL, 0, 0 ) ) {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
}

Edit

After re-reading your question, I think you're just looking for the AdjustWindowRect API. In which case, your question is a duplicate of this one: WinAPI: Create a window with a specified client area size. For future reference, the "area you can drawn on" is called the client area.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!