WINAPI CreateWindow Displaying Strange Results

265 views Asked by At

I'm having trouble with a WINAPI project. There are two problems, when I launch a window with the below code, the height parameter behaves strangely. It seems to cap off at 1092, 18 pixels below where I need it on my computer. The second problem is that the window has no edges nor the top menu bar, until I use the Windows+Up/Down key combination to minimize and maximize it, then it behaves normally. I'm using the below code to initialize the window (the only code that runs before this initializes the options.pxXRes and other variables used below):

//Set up the window class
WNDCLASSEX wndClass;
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = &WndHandleInput;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = GetModuleHandle(nullptr);


wndClass.hIcon = nullptr;
wndClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
wndClass.lpszMenuName = nullptr;
wndClass.lpszClassName = "ToastCatClass";
wndClass.hIconSm = nullptr;

RegisterClassEx(&wndClass);

RECT wndRect;
if (options.fullscreen) {
    wndRect.left = 0;
    wndRect.right = options.pxXRes;
    wndRect.top = 0;
    wndRect.bottom = options.pxYRes;
    AdjustWindowRect(&wndRect, WS_OVERLAPPEDWINDOW, false);
} else {
    wndRect.left = (GetPXXRes() - options.pxXRes) / 2;
    wndRect.right = options.pxXRes;
    wndRect.top = (GetPXYRes() - options.pxYRes) / 2;
    wndRect.bottom = options.pxYRes;
    AdjustWindowRect(&wndRect, WS_OVERLAPPEDWINDOW, false);
}

hWnd = CreateWindowEx(
    0,
    wndClass.lpszClassName,
    "ToastCat",
    WS_OVERLAPPEDWINDOW,
    wndRect.left,
    wndRect.top,
    wndRect.right - wndRect.left,
    wndRect.bottom - wndRect.top,
    nullptr,
    nullptr,
    wndClass.hInstance,
    nullptr
);

assert(hWnd != nullptr, "Failure to launch window.");

ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);

The Window procedure is as follows:

LRESULT __stdcall WndHandleInput(HWND hWndParam, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_NCCREATE:
        return true;
    case WM_KEYDOWN:
        switch (wParam) {
            //TODO: Update controls
        }
        break;
    case WM_KEYUP:
        switch (wParam) {
            //TODO: Update controls
        }
        break;
    case WM_CLOSE:
    case WM_QUIT:
        Cleanup();
        break;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }

    return 0;
}
1

There are 1 answers

1
Lukas Thomsen On BEST ANSWER

Windows have two different rectangles:

  • the client rectangle which is the area of the window to which the application can draw or create child windows within and
  • the window rectangle which is the outer rectangle of the window (including borders, menu, ...).

By calling AdjustWindowRect you're converting a client rectangle to a window rectangle. Therefore the borders and the menu cannot be visible if you're setting up a client rectangle as big as the entire screen, converting it to a window rectangle and creating a window with such size. If you look at wndRect after the call to AdjustWindowRect(..) using the debugger you will see that top and left are negative.

That the window height is off by some pixels is the default windows behavior. Windows by default does not allow windows to have a height bigger than the screen height because this will move the caption out of the area the mouse can get to. To change this you have to process message WM_GETMINMAXINFO:

case WM_GETMINMAXINFO:
    DefWindowProc(hWnd, msg, wParam, lParam);
    MINMAXINFO *pmmi = (MINMAXINFO*)lParam;
    pmmi->ptMaxTrackSize.x *= 2;   // just make it bigger...
    pmmi->ptMaxTrackSize.y *= 2;   // 
    return 0;

If you just want to start your window either maximized (with all controls and border visible) or at some other defined location just do the following: Create your window normally with the wndRect initialized within the else-part of if (options.fullscreen) and change the call of ShowWindow(..) as follows:

if (options.fullscreen)
{
    ShowWindow(hWnd, SW_MAXIMIZE);
}
else
{
    ShowWindow(hWnd, SW_SHOWDEFAULT);
}
UpdateWindow(hWnd);