Anon
Anon

Reputation: 1354

c++ / application with multiple separate windows

So i have this code that creates two windows:

WNDCLASS wc;
    wc.style = CS_BYTEALIGNCLIENT | CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = StaticWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = (HINSTANCE)GetModuleHandle(nullptr);
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = nullptr;
    wc.lpszClassName = _T("Move Engine");
    RegisterClass(&wc);
    m_hWnd = CreateWindow("Move Engine", "Move Engine", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, usWidth, usHeight, nullptr, nullptr, wc.hInstance, this);

    // Create the settings window
    wc.lpszClassName = _T("Settings");
    RegisterClass(&wc);
    s_hWnd = CreateWindow("Settings", "Settings", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 20, nullptr, nullptr, wc.hInstance, this);

ShowWindow(m_hWnd, SW_SHOW);
ShowWindow(s_hWnd, SW_SHOW);

The problem is, application terminates each time i close one of the windows. What i need is two separate windows; main application window and the one that gives access to various settings of the application - therefore closing the settings window should not affect the main window. Is there any way to achieve this? Thank you.


P.S. My WinMain function is modified like this:

int WINAPI WinMain(HINSTANCE a_hInstance, HINSTANCE a_hPrevInstance, LPTSTR a_lpCmdLine, int a_iCmdShow)
{
    int iReturnCode;

    // Initialise the engine.
    if (!MyEngine.InitInstance(a_hInstance, a_lpCmdLine, a_iCmdShow)) return 0;

    // Begin the gameplay process and return when the application due to exit
    iReturnCode = MyEngine.StartEngine();

    // Return the correct exit code.
    return iReturnCode;
}

and StaticWndProc looks like this:

LRESULT CALLBACK CMoveEngine::StaticWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    // If this is a create message, trap the 'this' pointer passed in and store it within the window.
    if (Message == WM_CREATE) SetWindowLong(hWnd, GWL_USERDATA, (LONG)((CREATESTRUCT FAR *)lParam)->lpCreateParams);

    // Obtain the correct destination for this message
    CMoveEngine *Destination = (CMoveEngine*)GetWindowLong(hWnd, GWL_USERDATA);

    // If the hWnd has a related class, pass it through
    if (Destination) return Destination->DisplayWndProc(hWnd, Message, wParam, lParam);

    // No destination found, defer to system...
    return DefWindowProc(hWnd, Message, wParam, lParam);
}

Message loop:

int CMoveEngine::StartEngine()
{
    MSG msg;
// Start main loop
while (true) 
{
    // Did we recieve a message, or are we idling?
    if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) 
    {
        if (msg.message == WM_QUIT) break;
        TranslateMessage(&msg);
        DispatchMessage (&msg);
    } 
    else 
    {

    }
}

return 0;
}

Upvotes: 3

Views: 2403

Answers (2)

Didier Trosset
Didier Trosset

Reputation: 37427

You register both window classes with the same lpfnWndProc. Thus, all the messages (including mouse clicks and keyboard presses) will be directed to the same function, StaticWndProc.

Thus, when this function receives the WM_CLOSE message, it will respond by destroying the window, which stops the message pump and terminates the program. Since both windows have the same message handler function, they will both respond in the same way.

The solution is to define two different WndProc methods, one for each of your windows, or special-case the handling of the WM_CLOSE message, only calling DefWindowProc for the window that you want to allow to close the entire application.

Upvotes: 3

Bernd Elkemann
Bernd Elkemann

Reputation: 23550

Make your StaticWndProc handle either WM_CLOSE or WM_DESTROY: In that case it should decrement an openedWindows-counter. If that counter reaches zero call PostQuitMessage.

Upvotes: 2

Related Questions