重新打开MFC模态对话框

5

我需要打开一个对话框,从同一个类实例化两次。当我尝试这样做时

CdelmeDlg dlg;
dlg.DoModal();
dlg.DoModal();

第二次调用仅打开对话框一瞬间,就立即关闭了。我猜测是消息队列中留下了未处理的消息,因此在两次调用之间添加了以下代码。
MSG msgCur;
while (::PeekMessage(&msgCur, NULL, NULL, NULL, PM_REMOVE))
    ;

这样做解决了问题,但感觉并不是正确的方法。有没有一种方式可以正确处理剩余的消息?

这看起来非常奇怪,你到底想要实现什么? - Nikola Smiljanić
我需要让我的应用程序在没有用户界面的情况下运行,并在每次定时器计时结束时弹出此对话框。 - MMx
你如何关闭对话框? - Aaron Fischer
但是你为什么要调用两次DoModal呢? - Nikola Smiljanić
为了隔离问题,我使用应用程序向导创建了一个空的基于对话框的应用程序。这将所有命令消息处理留给 MFC。如果我创建一个 OnBnClicked 方法,将其映射到处理按钮点击消息并从其中调用 EndDialog(IDOK),那么也会发生相同的事情。 - MMx
Nikola:我需要能够至少打开两次对话框。我也尝试了让第一个CdelmeDlg对象超出作用域,创建另一个对象并调用其DoModal()方法。结果是相同的。 - MMx
6个回答

1
为什么你不能像这样编写代码呢:
CdelmeDlg dlg; 
dlg.DoModal(); 

CdelmeDlg dlg1; 
dlg1.DoModal(); 

1

不要调用 EndDialog(IDOK);

为了处理按下 确定(ok) 或 取消(cancel) 按钮,只需继承 OnOk 或 OnCancel ... 否则 EndDialog 将被调用两次,你会遇到正在遇到的问题!


1

我认为YeenFei在这里提出了一个很好的观点。

我已经有一段时间没有使用MFC了(谢天谢地),但是从记忆中,计时器可能会或可能不会从UI线程调用,这取决于你使用哪个。如果计时器在主UI线程上被触发,那么模态对话框可能会阻止主线程直到它被解除,之后它将由下一个计时器调用。如果计时器在单独的线程上被触发,那么你的对话框不会阻塞主UI线程,因为它是在单独的线程上显示的。

正如YeenFei所指出的那样,你希望每次计时器被触发时重新显示对话框,在用户单击按钮关闭对话框时隐藏它。这样,如果时间再次被触发,它只是重新显示对话框,无论它当前是否打开。

这里有一篇关于计时器和并发的优秀文章(www.eggheadcafe.com),你可能会发现它很有趣,并且比我做的更清晰明了。


0
如果您想让应用程序在后台运行而没有用户界面,为什么不暂时隐藏它呢?一个简单的函数this->ShowWindow(SW_HIDE)就可以为您完成这项工作。
我认为您应该重新考虑设计决策,因为您想要的应用程序行为似乎是不合逻辑的。

0

也许你的代码有这样一行:

m_pMainWnd = &dlg;

如果是这样的话,那么在第一次调用DoModal()之后,应用程序将会结束,所有其他对DoModal()的调用都会返回-1。根据MSDN的说明:
微软基础类库将在m_pMainWnd所引用的窗口关闭时自动终止您的线程。如果该线程是应用程序的主线程,应用程序也将被终止。

0

我通过隐藏对话框而不是关闭它,并启动另一个线程来解决问题,该线程首先休眠,然后取消隐藏对话框。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接