如何让子进程窗口在我的进程中显示模态?

moo*_*ogs 8 windows winapi

我有一个应用程序调用一些其他实用程序应用程序来设置特定设备的一些设置.使用ShellExecuteEx调用该实用程序.

为了不混淆用户,最好将实用程序应用程序的窗口设置为我的主窗口.怎么做到这一点?

我试过的事情:

  1. ShellExecuteEx之后的进程上的WaitForSingleObjectEx,INFINITE TIMEOUT - 窗口是模态的,但主应用程序不重绘(因为它正在等待单个对象!)
  2. 在ShellExecuteEx之后的进程上WaitForSingleObjectEx,一些小超时,然后调用Peekmessage和DispatchMessage - 重绘现在可以工作,但实用程序应用程序不再是"模态".主应用程序响应鼠标点击,按钮点击等
  3. EnableWindow(FALSE),然后执行方法#2,然后执行EnableWindow(TRUE) - WORKS !!!,但在此之后,我的应用程序的z顺序发生了变化.(它现在低于其他窗口).为什么?!

Mat*_*ier 3

简而言之,即使线程位于同一进程中,也无法无缝地使线程 B 中的窗口成为线程 A 中窗口的模式。如果您拥有两个窗口的代码,您可能能够接近,但在这种情况下,通过将所有 UI 放在一个线程中,您将获得更好的结果。

如果您尝试向用户建议线程 B 的窗口对于线程 A 来说是模态的,那么您必须正确处理许多微妙的 Z 顺序和激活行为(正如您所注意到的),以免您遭受恐怖谷效应排序,用户很清楚线程 B 的窗口正在尝试成为它不是的东西,因此看起来已损坏。

为了避免这种情况,我会采取这种方法:

  1. 用户单击 canner.exe 主窗口中的“FDA Inspection”。canner.exe 显示一个模式对话框,指示它正在打开外部程序(“打开肉毒杆菌设置...”)。这会禁用主窗口等,以便用户知道正在发生模式交互。
  2. canner.exe调用ShellExecuteEx ()来启动botulism.exe。
  3. canner.exe在从 ShellExecuteEx() 返回的句柄上调用WaitForInputIdle ()。当 botulsim.exe 准备好进行用户交互时,WaitForInputIdle() 将返回(大约,但通常足够接近)。如果 botulism.exe 通常需要五秒或更长时间才能显示其 UI,我可以在循环中使用 WaitforInputIdle() 的短超时,并偶尔使用 PeekMessage()/ProcessMessage() 处理任何待处理的消息。
  4. canner.exe 更改其对话框文本以反映它正在等待用户关闭 botulism.exe(“关闭 Botulism 设置以继续...”)。
  5. canner.exe循环调用MsgWaitForMultipleObjects ()等待botulsim.exe关闭。当传递的句柄收到信号或线程队列中有消息等待时,MsgWaitForMultipleObjects() 将返回。
  6. 如果用户在 canner.exe 等待时单击 canner.exe 模式对话框中的关闭框,则 canner.exe 会提示用户 botulism.exe 仍在运行(“Botulism 设置仍然打开,仍要继续吗?”、“是的,我知道”或“不,我还没完成”)。如果得到确认,canner.exe 将关闭对话框并取消在步骤 1 中启动的原始 FDA 检查并返回到主窗口的消息循环。
  7. 当 MsgWaitForMultipleObjects() 指示 botulism.exe 已完成时,canner.exe 会关闭对话框并正常继续步骤 1 中开始的 FDA 检查。

这样,如果一切正常且快速地进行,则交互很可能是无缝的,但如果子进程出现问题或 Z 顺序发生更改等,就会清楚父进程为何等待以及用户正在做什么需要取消或继续他开始的任务。