Why is C++ ShowWindow() not working properly when hiding a window and showing another?

1.7k views Asked by At

I am writing my first Win32 app in C++ and I am trying to create 3 windows between which to redirect based on what buttons the user clicks on. I initialised the windows (window1,window2,window3) as children of the main window hwnd and only set window1 as visible. window1 also has two buttons, each of which is supposed to direct either to window2 or window3.

I tried to hide window1 and show which window I want to switch to using the ShowWindow() function. However, it is not working (clicking the buttons does nothing). Could you help me understand why?

On another piece of code I had before, where I had not created window1, and the buttons and the other two windows were just children of hwnd, pressing the button did show the right window, but the button remained there, even if it did not belong on that window.

Also, is there a more efficient way of switching between windows (without deleting and creating them again and again?

Thanks!!!

EDIT: I managed to solve my problem. It arose from the fact that I had declared windows 1,2 and 3 as static. By declaring them under the same class as hwnd, I was able to process the messages from the buttons under the main WindowProcedure(). Since my program is gonna be quite simple, I do not need to create a different procedure for the new windows, but thanks to the comments, now I also know how to do that!

    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
            case WM_CREATE:
    
                window1 = CreateWindow("STATIC","Window 1",WS_VISIBLE|WS_BORDER|WS_CHILD,0,0,600,600,hwnd,NULL,NULL,NULL);
                window2 = CreateWindow("STATIC","Window 2",WS_BORDER|WS_CHILD,0,0,600,600,hwnd,NULL,NULL,NULL);
                button2 = CreateWindow(
                                       "BUTTON",
                                       "SECOND WINDOW",
                                       WS_CHILD | WS_VISIBLE | WS_BORDER,
                                       350, 480,
                                       200, 20,
                                       window1, (HMENU) 2, NULL, NULL);
                window3 = CreateWindow("STATIC","Window 3",WS_BORDER|WS_CHILD,0,0,600,600,hwnd,NULL,NULL,NULL);
                button3 = CreateWindow(
                                       "BUTTON",
                                       "THIRD WINDOW",
                                       WS_CHILD | WS_VISIBLE | WS_BORDER,
                                       50, 480,
                                       200, 20,
                                       window1, (HMENU) 3, NULL, NULL);
                break;
    
            case WM_COMMAND:
    
                switch(LOWORD(wParam))
                {
                    case 2:
                        ShowWindow(window1,SW_HIDE);
                        ShowWindow(window2,SW_SHOW);
                        break;
                    case 3:
                        ShowWindow(window1,SW_HIDE);
                        ShowWindow(window3,SW_SHOW);
                        break;
                }
    
            break;
            case WM_DESTROY:
                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
                break;
            default:                      /* for messages that we don't deal with */
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }

1

There are 1 answers

0
Zeus On BEST ANSWER

First, create a new window1 as in the steps of creating the main form.

Then create a windowprocessforwindow1 for window1, process the WM_COMMAND message in this function.

Here is the sample:

#include <Windows.h>

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK windowprocessforwindow1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static HWND  window1, window2, button2, window3, button3;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("hello windows");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WindowProcedure;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
    }

    hwnd = CreateWindow(szAppName,
        TEXT("the hello program"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        static HINSTANCE hInstance;
        static WNDCLASSEX win1;
    case WM_CREATE:
        hInstance = (HINSTANCE)::GetWindowLong(hwnd, GWL_HINSTANCE);
        win1.hInstance = hInstance;
        win1.lpszClassName = L"Window 1";
        win1.lpfnWndProc = (WNDPROC)windowprocessforwindow1;      /* This function is called by windows */
        win1.style = CS_DBLCLKS;                 /* Catch double-clicks */
        win1.cbSize = sizeof(WNDCLASSEX);
        win1.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        win1.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
        win1.hCursor = LoadCursor(NULL, IDC_ARROW);
        win1.lpszMenuName = NULL;                 /* No menu */
        win1.cbClsExtra = 0;                      /* No extra bytes after the window class */
        win1.cbWndExtra = 0;                      /* structure or the window instance */
        win1.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
        if (!RegisterClassEx(&win1))
            return 0;
        window1 = CreateWindowEx(
            0,                   /* Extended possibilites for variation */
            L"Window 1",         /* Classname */
            L"Window 1",       /* Title Text */
            WS_VISIBLE | WS_BORDER | WS_CHILD, /* default window */
            0,       /* Windows decides the position */
            0,       /* where the window ends up on the screen */
            600,                 /* The programs width */
            600,                 /* and height in pixels */
            hwnd,        /* The window is a child-window to desktop */
            NULL,                /* No menu */
            hInstance,       /* Program Instance handler */
            NULL                 /* No Window Creation data */
        );
        window2 = CreateWindow(L"STATIC", L"Window 2", WS_BORDER | WS_CHILD, 0, 0, 600, 600, hwnd, NULL, NULL, NULL);
        button2 = CreateWindow(
            L"BUTTON",
            L"SECOND WINDOW",
            WS_CHILD | WS_VISIBLE | WS_BORDER,
            350, 480,
            200, 20,
            window1, (HMENU)2, NULL, NULL);
        window3 = CreateWindow(L"STATIC", L"Window 3", WS_BORDER | WS_CHILD, 0, 0, 600, 600, hwnd, NULL, NULL, NULL);
        button3 = CreateWindow(
            L"BUTTON",
            L"THIRD WINDOW",
            WS_CHILD | WS_VISIBLE | WS_BORDER,
            50, 480,
            200, 20,
            window1, (HMENU)3, NULL, NULL);
        ShowWindow(window1, SW_SHOW);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);       /* send a WM_QUIT to the message queue */
        break;
    default:                      /* for messages that we don't deal with */
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

LRESULT CALLBACK windowprocessforwindow1(HWND handleforwindow1, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_COMMAND:
    {
        switch (wParam) {
        case 2:
            ShowWindow(window1, SW_HIDE);
            ShowWindow(window2, SW_SHOW);
            break;
        case 3:
            ShowWindow(window1, SW_HIDE);
            ShowWindow(window3, SW_SHOW);
            break;
        }
    }
    return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:

        return DefWindowProc(handleforwindow1, msg, wParam, lParam);
    }
    return 0;
}