【问题标题】:c++ / application with multiple separate windowsc++ / 具有多个单独窗口的应用程序
【发布时间】:2025-12-19 20:55:07
【问题描述】:

所以我有这个创建两个窗口的代码:

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

问题是,每次我关闭一个窗口时,应用程序都会终止。我需要的是两个独立的窗口;主应用程序窗口和一个可以访问应用程序各种设置的窗口 - 因此关闭设置窗口不应影响主窗口。有没有办法实现这一目标?谢谢。


附:我的 WinMain 函数修改如下:

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

StaticWndProc 看起来像这样:

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

消息循环:

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

【问题讨论】:

  • StaticWndProc 对 WM_CLOSE 等的响应是什么?你的消息循环是什么样的?
  • @Tom Whittock 它发布了一条退出消息:PostQuitMessage(0);

标签: c++ winapi


【解决方案1】:

您使用相同的lpfnWndProc 注册两个窗口类。因此,所有消息(包括鼠标点击和键盘按下)都将被定向到相同的函数StaticWndProc

因此,当此函数接收到WM_CLOSE message 时,它会通过销毁窗口来响应,从而停止消息泵并终止程序。由于两个窗口具有相同的消息处理函数,它们都会以相同的方式响应。

解决方案是定义两个不同的WndProc 方法,一个用于您的每个窗口,或者处理WM_CLOSE 消息的特殊情况,只为您要允许关闭的窗口调用DefWindowProc整个应用程序。

【讨论】:

  • 您的记忆完全正确。我冒昧地稍微扩展了您的答案,并删除了自我怀疑的迹象。希望你不要介意! :-)
  • 你能告诉我在上面的上下文中我应该如何实现第二个StaticWndProc函数吗?
【解决方案2】:

使您的StaticWndProc 处理WM_CLOSEWM_DESTROY:在这种情况下,它应该减少openedWindows 计数器。如果该计数器达到零,请调用PostQuitMessage

【讨论】:

  • 我刚刚阅读了一些关于这个案例的内容,但我仍然不清楚 - 有没有办法让每个窗口都收到自己的一组消息?
  • @Abdulali:是的,当您使用RegisterClass 创建每个窗口时,为每个窗口注册一个不同的WndProc 函数。
最近更新 更多