如何显示无模式对话框并立即显示信息?

时间:2008-12-22 10:16:42

标签: mfc dialog modeless

我想在屏幕上显示无模式对话框并在其中显示一些信息。

但是,如果我按照以下方式使用它,它会遇到一些问题:

function()
{
showdialog(XXX).
//heavy work.
update the dialog..
//heavy work.
update the dialog...
}

似乎显示了对话框,但它不会在其中绘制任何信息。它只在函数结束时绘制所有信息。

如何修改无模式对话框以便立即显示信息?

4 个答案:

答案 0 :(得分:6)

你可以做一些事情。

(1)您可以 CDialog :: OnInitDialog 方法中发布消息,然后处理该函数中的long函数该发布消息的消息处理程序。这样,对话框将首先显示,然后长函数将运行。

(2)第二个选项是确保消息循环获得一些处理时间。因此,如果您的长函数是某种循环,只需添加偶尔调用 ProcessMessages 以确保消息队列保持为空:

void ProcessMessages()
{
    MSG msg;
    CWinApp* pApp = AfxGetApp();
    while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
    {
        pApp->PumpMessage();
    }
}

编辑:当然可以使用线程就是这种情况,但这样做并不总是没有风险和复杂性。

使用带有 GUI 的线程意味着必须处理多个消息队列,这意味着使用像 PostThreadMessage 这样的API,这引入了一组需要警惕的新问题。

有关此类问题的示例,请参阅此链接:

http://msdn.microsoft.com/en-us/library/ms644946(VS.85).aspx

在哪里说:

  

PostThreadMessage发送的消息是   与窗口无关。作为一个   一般规则,不是的消息   与窗口关联不能   由DispatchMessage调度   功能。因此,如果收件人   线程处于模态循环中(由...使用)   MessageBox或DialogBox),.   消息将丢失。拦截   在模态中的线程消息   循环,使用特定于线程的钩子。

我在Zeus IDE中使用流程消息方法,它确保GUI保持对用户的响应非常有效。它还具有易于实现的优点。

答案 1 :(得分:5)

在OnInitDialog中,启动工作线程以执行计算。从工作线程发布用户消息以更新对话框。

由于以下几个原因,这优于ProcessMessages实现:

  • 执行计算的代码可以从不属于它的UI代码中分离出来。

  • 在执行实际计算时,UI仍保持响应。 ProcessMessages允许在单个计算功能期间进行多个UI更新,但在实际计算过程中仍将阻止UI。

对话框代码:

#define WM_NEW_COUNT (WM_USER + 0x101)

BEGIN_MESSAGE_MAP()
    ON_MESSAGE(WM_NEW_COUNT, OnNewCount)
END_MESSAGE_MAP()

BOOL CMyDialog::OnInitDialog()
{
    CWinThread* pThread = AfxBeginThread(MyCountFunc, this->GetSafeHwnd());
    return TRUE;
}

LRESULT CMyDialog::OnNewCount(WPARAM wParam, LPARAM)
{
    int newCount = (int)wParam;

    // m_count is DDX member, e.g. for label
    m_count = newCount;

    UpdateData(FALSE);

    return 0;
}

工作线程:

UINT MyCountFunc(LPVOID lParam)
{
    HWND hDialogWnd = (HWND)lParam;

    for (int i=0; i < 100; ++i)
    {
        PostMessage(hDialogWnd, WM_NEW_COUNT, i, NULL);
    }
}

答案 2 :(得分:2)

根据经验,重型计算不应该放在GUI线程中。由于它是一个无模式对话框,因此对话框不会拥有消息循环。 ProcessMessage()解决方案可行,但IMO不是正确的方法。我的建议是: 1)在OnInitDialog()中生成一个新线程 2)当有趣的事情发生时,让单独的线程向对话框发布消息。其中一个有趣的事情是工作已经完成。

但请注意,这意味着您需要执行正确的同步。

答案 3 :(得分:1)

不要试图一次性完成繁重的工作。让对话框在OnInitDialog的WM_APP范围内发布消息。 WM_APP处理程序可以完成部分繁重的工作,然后执行另一个PostMessage并返回。通过这种方式,您允许消息泵处理您的处理块之间的窗口消息。