Ray Siplao
Ray Siplao

Reputation: 199

How to resize window after adding menubar

When I add a menubar to a window, the window didn't resize accordingly because the top portion is hidden by the menubar. I want to resize the window while taking account of menubar's height. This is what I tried.

/* g++ test.cpp -o test -Wl,-subsystem,windows */

#include <Windows.h>

#define ID_OPEN 0
#define ID_EXIT 1
#define ID_ABOUT 2

const int width = 500;
const int height = 400;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szWndClassName[] = TEXT("hellowin");
    HWND hWnd;
    MSG msg;
    WNDCLASS wndclass;

    //Step 1: Registering the Window Class
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szWndClassName;

    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("This program only works in Windows NT or greater!"), TEXT("Hey dude!"), MB_OK | MB_ICONERROR);
        return 1;
    }

    // Step 2: Creating the Window
    hWnd = CreateWindow(szWndClassName, /* window class name */
                        TEXT("Hey!"), /* window title (or caption) */
                        WS_OVERLAPPEDWINDOW, /* window style */
                        CW_USEDEFAULT, /* initial x position */
                        CW_USEDEFAULT, /* initial y position */
                        width, /* initial window width */
                        height, /* initial window height */
                        NULL, /* parent window handle */
                        NULL, /* window menu handle */
                        hInstance, /* program instance handle */
                        NULL); /* creation parameters */

    if (hWnd == NULL)
    {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

    // Step 3: The Message Loop (heart)
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

// Step 4: the Window Procedure (brain)
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE:
    {
        HMENU hMenuBar = CreateMenu();
        HMENU hFile = CreatePopupMenu();
        HMENU hHelp = CreatePopupMenu();

        AppendMenu(hMenuBar, MF_POPUP, (UINT_PTR) hFile, "File");
        AppendMenu(hMenuBar, MF_POPUP, (UINT_PTR) hHelp, "Help");

        AppendMenu(hFile, MF_STRING, ID_OPEN, "Open");
        AppendMenu(hFile, MF_STRING, ID_EXIT, "Exit");

        AppendMenu(hHelp, MF_STRING, ID_ABOUT, "About");

        SetMenu(hWnd, hMenuBar);

        PMENUBARINFO pmbi;

        GetMenuBarInfo(hWnd, OBJID_MENU, 0, pmbi);

        RECT menuRect;
        RECT windRect;

        GetWindowRect(pmbi->hwndMenu, &menuRect);
        GetWindowRect(hWnd, &windRect);

        int width = menuRect.right - menuRect.left;
        int height = (menuRect.bottom - menuRect.top) + (windRect.bottom - windRect.top);

        SetWindowPos(hWnd,
                     0,
                     0,
                     0,
                     width,
                     height,
                     SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);

        break;
    }
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        RECT rect;

        GetClientRect(hWnd, &rect);
        DrawText(hdc, TEXT("Hello World!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        EndPaint(hWnd, &ps);

        break;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }

    return 0;
}

I tried to retrieve rectangles of both menubar and the window and calculate the new dimension like this

        int width = menuRect.right - menuRect.left;
        int height = (menuRect.bottom - menuRect.top) + (windRect.bottom - windRect.top);

Unfortunately the code crashes. I have no idea which part I did wrong. Any ideas?

Upvotes: 0

Views: 269

Answers (1)

catnip
catnip

Reputation: 25408

pmbi is an uninitialised pointer variable. Passing it to GetMenuBarInfo is therefore the likely cause of your crash. If that doesn't crash, then attempting to access pmbi->hwndMenu probably will.

Instead, you want:

MENUBARINFO mbi;
mbi.cbSize = sizeof (mbi);  // see documentation
GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi);
...

which tells GetMenuBarInfo to fill in the (stack-based) variable mbi.

Then replace pmbi->hwndMenu with mbi.hwndMenu and that should fix your problem.

Upvotes: 1

Related Questions