Winapi 如何在非模态对话框中模拟模态对话框UI行为?

Winapi 如何在非模态对话框中模拟模态对话框UI行为?,winapi,mfc,Winapi,Mfc,有没有一种简单的方法可以无模式显示对话框,同时保留阻止模式对话框提供的UI 我想在显示对话框时停止用户与其他对话框/控件的交互,但让应用程序继续运行。有没有办法将对话框设置为“独占焦点”或类似的内容?未经测试,但您可以尝试禁用所有者窗口(应用程序主窗口),创建无模式对话框,然后在关闭对话框时再次启用它: 要禁用主窗口,请执行以下操作: AfxGetMainWnd()->EnableWindow(FALSE); 要创建模式/非阻塞对话框,请执行以下操作: dlg->Create(re

有没有一种简单的方法可以无模式显示对话框,同时保留阻止模式对话框提供的UI


我想在显示对话框时停止用户与其他对话框/控件的交互,但让应用程序继续运行。有没有办法将对话框设置为“独占焦点”或类似的内容?

未经测试,但您可以尝试禁用所有者窗口(应用程序主窗口),创建无模式对话框,然后在关闭对话框时再次启用它:

要禁用主窗口,请执行以下操作:

AfxGetMainWnd()->EnableWindow(FALSE);
要创建模式/非阻塞对话框,请执行以下操作:

dlg->Create(resId)
要在OnClose事件或类似事件中再次启用它:

AfxGetMainWnd()->EnableWindow(TRUE);

在模态对话框中可能还有我不知道的其他细节。如果您愿意进行调查,请阅读MFC的源代码
CDialog::DoModal()
。如果我没记错的话,这个MFC函数使用无模式Win32 API模拟一个模式阻塞对话框,以实现全局加速器、钩子、消息等。

不,没有简单的方法可以实现您想要的

如果你真的想走你描述的路线,我建议你首先阅读陈雷蒙博客上的整个“情态”系列。第一期正在进行


然而,这似乎是XY问题的一个例子。你想做什么?让主应用程序不断更新自身?如果是这样的话,我认为(根据我们得到的信息)调用AfxPumpMessage()可以满足您的需要。还是要继续处理主应用程序中的数据?然后,您将通过使用辅助线程来拯救自己的世界。

以下是您问题的可能答案:

您可以禁用应用程序中的所有其他控件,然后在对话框完成后重新启用它们

使用此回调

BOOL CALLBACK EnableDisableAllChildren ( HWND hwnd, LPARAM lp ) 
{
    ::EnableWindow ( hwnd, (BOOL)lp );

    return TRUE;
}
打电话给

  EnumChildWindows ( HWNDToYourApp, EnableDisableAllChildren, true );
做情态动词对话

  EnumChildWindows ( HWNDToYourApp, EnableDisableAllChildren, false );  

有什么不同的想法。

您是否尝试过
启用窗口(mainWnd,FALSE)
然后
创建对话框(mainWnd,…)
?我在MFC中工作,但我认为您的问题转移了-但是我不确定从对话框启动的位置获取
mainWnd
有多容易。尽管如此,您还是可以基于此提交答案。好吧,您仍然需要所有者窗口来创建对话框。或者,如果使用默认主窗口,只需使用
AfxGetMainWnd()
。我没有将其作为答案发布,因为我不知道它是否会工作或看起来很奇怪,只是一个想法……我们将NULL作为父窗口传递,MSDN说:“如果为NULL,对话框对象的父窗口将设置为主应用程序窗口”。因此,
AfxGetMainWnd()
可能是合适的。我会说将其作为答案发布,但请注意它未经测试。“我想在显示对话框时停止用户与其他对话框/控件的交互,但让应用程序继续运行。”换句话说,您需要一个模式对话框。我遗漏了什么?我认为这基本上与Chen在博客Roel links to(新旧事物,模态第1部分)中提供的解决方案相同。当对话框管理器关闭对话框时,它将输入焦点转移到适当的窗口。必须启用潜在候选人。由于对话框关闭时应用程序的所有子窗口仍处于禁用状态,因此您失去了恢复输入焦点的最后机会。此应用程序将不会公开可用的键盘界面。@IInspectable他可能会在对话框中禁用和启用它自己对发布的解决方案进行评论。如果它附带了一个免责声明,大意是“必须修复才能使其工作”,那么它就不是一个解决方案。虽然可以解决此缺陷,但它不是唯一的缺陷:在对话框关闭时无条件地启用所有子窗口也将启用最初禁用的窗口,或由于用户与对话框交互而禁用的窗口。解决方案变成了一个需要解决的难题。