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

房东的猫 提交于 2019-12-07 09:30:45

问题


I've noticed something very annoying while trying to create a window in C++ and draw Rectangles that the window size doesn't match the size I set.

For example, If I set the 480x240 window and try to Draw rectangles from top to bottom, left to right by getting GetWindowRect(hwnd, &rect) and calculate the width and height:

rectangle_width = (rect.right - rect.left) / amountRectangleX;
rectangle_height = (rect.bottom - rect.top) / amountRectangleY;

if amountRectangleX = 2 and Y = 2 it draw 4 rectangles, but the width and height is "off" so it doesn't fill up the whole screen or it renders over it. The only way this can happen (I've done this in alot of other languages so I know it works) is that if I set Window Size = 480x240 I want that to be the area to "DRAW" on. Because if borders are included in the size of the window - that would be different on another computer with different Window Style and such. ANd I can't just "alter" this manually for my computer.

If I set window size = 480x240 and take a screenshot I see that the Window Space = 452x232 which is confusing. It would be OK if I set window size = 480x240 but when I GetWindowRect() I get 452x232 and not 480x240 which then is invalid because I have less space to draw on. This would explain why my Rectangles render beyond the window space and I do NOT want that. But I still want to be able to set my size = 480x240 or anything else but still have borders.

Why does it work this way and is there a solution to this problem? I can't be the only one that want to be able to set the resolution of a window and no matter what computer you use, that size you set IS the DRAW AREA that you can draw upon.


回答1:


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

}



回答2:


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.



回答3:


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.



来源:https://stackoverflow.com/questions/11783086/get-exact-window-region-size-createwindow-window-size-isnt-correct-size-of-wi

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