2009-12-28 123 views
3

我已经写了,其中有两个线程的样本MFC应用程序: - 主线程(UI线程) -Worker线程(非UI线程)如何在工作线程(非UI线程)中创建模态对话框?

我有一个具体的要求,以创建一个非对话框Modal -UI(工作者线程)。 当我创建CDialog对象并调用DoModal时,它可以工作。对话框被创建并作为应用程序的模态。 (Win XP SP2机器)但是这在Windows 2003服务器机器中不起作用。 2003服务器的行为是,模态对话框在应用程序的主窗口后面,只有当我点击主窗口时,对话框才会出现在前面。它不作为我的应用程序的模态对话框。

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

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

回答

1

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

0

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

2

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

不过,如果你一定要,你可以在下面的步骤另一个线程模式一个对话框:

  1. 创建对话框时,通过你的活动窗口作为所有者。
  2. 当显示对话框时,遍历其他窗口并执行它们EnableWindow(FALSE)。当对话框隐藏时,请做相反的操作。您可能必须记住Windows的启用状态并恢复原始状态,而不仅仅是EnableWindow(TRUE)
  3. 确保在显示对话框时忽略加速器和其他全局命令。

请注意,(2)不应该是必要的,只要你做(1),但你已经提到MFC,我不记得它究竟是如何表现。它有自己的模式对话框实现,它可能不完全符合Win32。如果你幸运的话,(1)和(3)就足够了。

2

没有可靠的方法来跨多个线程传播GUI模态。每个窗口都由一个HWND引用的对象表示,而该对象又具有线程关联性。这是从Windows的16位日子剩下的,那里没有多线程。因此,HWND不受并发访问保护。 The Old New Thing在“用户界面对象的线程亲和性”(部分123Addendum)上有很好的系列。

Modality通过首先启用对话框窗口然后禁用其父项来实现。第一步是安全的,而第二步则尝试从不是窗口拥有线程的线程中禁用窗口。由于en//禁用窗口修改通过HWND引用的对象,它代表竞争条件。

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