如何在工作线程(非UI线程)中创建模态对话框?

时间:2009-12-28 10:34:42

标签: c++ windows mfc winapi modal-dialog

我编写了一个示例MFC应用程序,其中有两个线程:      - 主线程(UI线程)      - 工作线程(非UI线程)

我有一个特定的要求,即在非UI(工作线程)中创建Modal对话框。 当我创建CDialog对象并在其上调用DoModal时,它可以正常工作。该对话框已创建并充当应用程序的模态。 (Win XP SP2机器)但这在Windows 2003服务器机器上不起作用。 2003服务器中的行为是,模态对话框落后于应用程序主窗口,只有当我单击主窗口时,对话框才会显示在前面。它不是我的应用程序的模态对话框。

可能是什么问题 - 任何想法?

如果在非UI线程中创建UI控件是问题,那么是否有任何Win32 API允许我将我的工作线程链接到主UI线程,以便在主线程中发生DoModal。我试过了AttachThreadInput,但它没有用。

4 个答案:

答案 0 :(得分:2)

首先,我想同意其他海报,可能最好在主UI线程上显示对话框。

但是,如果必须,您可以使用以下步骤在另一个线程模式上进行对话:

  1. 在创建对话框时将您的活动窗口作为所有者传递。
  2. 当显示对话框时,迭代其他窗口并执行EnableWindow(FALSE)。对话框隐藏时,反过来。您可能必须记住Windows启用状态并恢复原始状态,而不仅仅是EnableWindow(TRUE)
  3. 确保在显示对话框时忽略加速器和其他全局命令。
  4. 请注意,(2)不应该是必要的,只要你做(1),但你已经提到了MFC,我不记得它的确切行为。它有自己的模态对话框实现,可能与Win32不完全匹配。如果你很幸运,(1)和(3)就足够了。

答案 1 :(得分:2)

没有可靠的方法在多个线程中传播GUI模态。每个窗口都由一个HWND引用的对象表示,而HWND又具有线程关联性。这是Windows的16位天的遗留问题,没有多线程。因此,HWND不受并发访问保护。 The Old New Thing有一个关于“用户界面对象的线程关联性”的优秀系列文章(部分1 2 3 Addendum)。

通过首先启用对话框窗口然后禁用其父窗口来实现模态。第一步是安全的,而第二步是尝试从不是窗口拥有线程的线程禁用窗口。由于启用/禁用窗口会修改通过{{1}}引用的对象,因此它表示竞争条件。

建议的解决方案是将GUI限制在单个线程中,并从工作线程与GUI线程进行通信,以使其代表工作线程执行用户交互。完成此操作的最简单方法是从工作线程调用SendMessage以阻止,直到GUI线程的消息处理程序返回。如果在显示对话框时工作线程应继续运行,则可以使用PostMessage代替并使用PostThreadMessage与工作线程进行通信,或发信号通知Event Object等同步对象。

答案 2 :(得分:1)

虽然我不知道Server 2003上对话框处理的细节,但是获取主线程的最简单的解决方法是使用自定义窗口消息,执行::SendMessage()并在消息中显示对话框处理程序。

答案 3 :(得分:0)

我建议你不要做主题建议的问题,并将所有UI限制在一个线程中。如果您需要其他线程与用户通信,请创建一些消息传递机制,要求UI线程执行此操作,然后将结果传回。