1

我在 WTL 中有一个 GUI 窗口,它在 CMessageLoop 实例内的线程内运行,该实例已添加到应用程序实例并运行。现在,在主 GUI 内的按钮处理程序中,我创建了一个新窗口。一旦我单击该按钮并创建窗口并尝试将退出消息发布到主 GUI 循环。编码:

主窗口,有自己的线程:

    CMessageLoop theLoop;
    _MyppModule.AddMessageLoop(&theLoop);
    if(m_pMyDlg == NULL) {
        m_pMyDlg = new CMyDlg();
        if(!IsWindow(*m_pMyDlg))
        {
            m_pMyDlg->Create(NULL);
            m_pMyDlg->ShowWindow(SW_SHOW);
            nRet = theLoop.Run();
            _MyppModule.RemoveMessageLoop();
        }
    }

按钮处理程序和子窗​​口创建:

LRESULT CMyDlg::OnButtonClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{

     ChildWindowDlg childDlg;
     childDlg.Create(m_hWnd);

     childDlg.ShowWindow(SW_SHOW);

     CMessageLoop _loop;
     );

     _loop.Run();
     ::DestroyWindow(childDlg);

     return S_OK;
}

现在,如果我单击 MyDlg 窗口中的关闭按钮,按钮的处理程序将被调用,在其中我会调用它,::PostQuitMessage但它永远不会从第一个代码片段到达 theLoop 消息循环。这发生在我退出第二个循环之后,因此 _loop 被破坏并且子对话框被破坏。这里发生了什么?

4

2 回答 2

2

你在这里有两个消息循环,孩子的一个是嵌套的。另一方面,消息队列是每个线程一个,并由最内部的消息循环(带有GetMessage)抽取。因此,WM_QUIT消息被内部的消息循环检索到CMyDlg::OnButtonClicked

于 2013-09-19T14:39:14.833 回答
0

第二个代码片段完全不自然。如果您的目标是弹出一个窗口,然后关闭,然后您想完成按钮单击处理程序的执行,那么您需要模态对话框:

LRESULT CMyDlg::OnButtonClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, 
                                BOOL& bHandled)
{
     ChildWindowDlg childDlg; // Add constructor parameters if needed
     // Additional initlaization calls might go here
     const INT_PTR nResult = childDlg.DoModal(m_hWnd); // DoModal handles it all
     if(nResult == IDOK) { ... } // Hey's we even have result coming from `EndDialog`
     return 0; // No S_OK here
}

没有消息循环,没有PostQuitMessage,不需要单独的窗口创建/销毁调用。这就是模态对话框的用途。


如果您不想阻止“调用”窗口,并且想法是让主窗口和从属窗口并排运行(或者,一个是另一个的一部分,无论如何都要同时响应),那么您不想阻止您的消息处理程序。处理程序将创建窗口并设置它 ( .Create, .ShowWindow) 然后退出OnButtonClicked函数。

两个窗口都已创建,都处于活动状态,并且它们的消息由顶级消息循环发送给它们。这是正确的方法,通常每个线程不需要多个消息循环。有时它可能对特定操作有意义,但这确实很少见。Windows 是被动实例。他们使用消息处理程序响应消息。线程消息循环服务于所有线程窗口,因为它所做的是DispatchMessageAPI 调用,它反过来寻找目标窗口,获取它WndProc并调用它来处理消息细节。

于 2013-09-19T15:29:24.023 回答