【问题标题】:c++, mfc - messagebox display, main window has a cancel button. prevent cancel while messagebox is activec++, mfc - 消息框显示,主窗口有一个取消按钮。在消息框处于活动状态时防止取消
【发布时间】:2013-03-08 10:49:05
【问题描述】:

我有一个奇怪的问题。考虑以下场景:

  • 主窗口在单击某个按钮时创建一个子对话框。
  • 子对话框在工作线程中执行某些任务。
  • 该任务期间发生错误,导致显示一个消息框,内容类似于“哎呀!出了问题。”。
  • 单击子对话框的“取消”按钮导致子对话框关闭。
  • 消息框仍处于活动状态!点击消息框中的任何内容 = 崩溃。

事情发生的伪代码:(请忽略此处的语法正确性)

MainWindowClass mainObj;

void MainWindowClass::OnSomeButtonClick()
{
    SomeDialogClass someDialogObj;
    someDialogObj.DoModal();
}

int MainWindowClass::doTask()
{
    // Do work
    if(ERROR)
    {
        MessageBox("Yikes! Something went wrong.", "Error", MB_OK);
        return ERROR;
    }
} 

///////////////////////////////////////////////////////////////////
// Meanwhile, in another file,

extern MainWindowClass mainObj;

void SomeDialogClass::OnCancel()
{
    // Do all cleanup and close dialog
}

int SomeDialogClass::workerThreadFunc()
{
    return mainObj.doTask();
}

int SomeDialogClass::DoModal()
{
    AfxBeginThread(workerThreadFunc);
    // Do all other work and then wait for the worker thread
}

我的问题有两个:

  1. 取消时,有没有办法知道是否有任何消息框/对话框 同一个应用程序处于活动状态?
  2. 我的整个设计都错了吗?我应该完全做其他事情吗?

我认为使用模态对话框的主要原因之一是它能够防止焦点转到父对话框。然而,当显示该错误消息框时,我可以愉快地单击对话框,然后单击“取消”并假装错误消息框从未显示。

【问题讨论】:

  • 我怀疑在 Cancel 上没有正确清理东西,因此你会崩溃。
  • @TonyTheLion,如果我在点击“取消”之前消除错误,则不会发生崩溃。发生崩溃是因为消息框的IsWindow() 断言失败。
  • 那么你的问题是什么?
  • "取消时,有没有办法知道同一应用程序中的任何消息框/对话框是否处于活动状态?"
  • @TonyTheLion,我很抱歉拒绝了你的建议。我做了一些愚蠢的假设。我应该将我的结果作为答案/问题/评论发布吗?感谢您的评论顺便说一句

标签: c++ windows mfc messagebox


【解决方案1】:

与其让您的工作线程显示模式消息框,不如将错误情况发回给 UI 线程。我对 MFC 和多线程的经验是,在同一个线程中处理所有 UI 会使事情变得更加简单,并消除这些类型的错误。有两个线程可能同时打开模式对话框是自找麻烦。

【讨论】:

  • 哦,这听起来比我的设计要好得多。感谢您的回答!
  • 几年前我自己开始将多线程与 MFC 混合时犯了完全相同的错误,并且发生了很多崩溃。强大的多线程比乍看起来要复杂得多。
【解决方案2】:

我对此有点陌生,但我的建议是,如果出现错误时要取消孩子,然后在启动错误之前将其销毁。

据我所知,SomeDialogClass 是模态的,然后父级启动另一个模态对话框 MessageBox。现在,如果 SomeDialogClass 是无模式的,那么消息框将出现在顶部,因为 SomeDialogClass 将是整个桌面的子级,而 MainWindowClass 的唯一子级将是 MessageBox。

我的印象是,模态只会阻止焦点转到模态对话框下方的内容,而不是在顶部或打开后启动的内容。我已经完成了一个模态对话框,从中启动了一个非模态对话框,并且可以很好地在屏幕上移动。此外,我创建了一个从无模式对话框返回到模式的 WM_MESSAGE,以宣布它何时完成,以便无模式可以完成。

【讨论】:

  • 实际上您的建议正是正在发生的事情。子对话框总是在错误显示之前关闭。我以为消息框活着导致了崩溃,但我错了。发生的事情是,在SomeDialogClass::OnCancel() 清理了所有分配的内存之后,SomeDialogClass::workerThreadFunc() 试图访问其中的一些(我上面的示例过于简化,抱歉)。这就是导致坠机的原因。但无论如何,谢谢你的建议!我一定会在我的下一个设计中记住它!
  • 另外,你对模态对话框有点不理解。模态对话框只能防止它们的 parent 窃取焦点。父对象是调用对象(依次是调用对象的调用对象,依此类推)。哪个先绘制或哪个在下面都没有关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多