【问题标题】:MFC application and a non-MFC modal dialogMFC 应用程序和非 MFC 模式对话框
【发布时间】:2023-06-02 12:56:02
【问题描述】:

我正在为第三方 MFC 应用程序编写 Win32 插件 DLL。 DLL 需要显示一个模式对话框。当我使用DialogBox() 或其他普通的 Win32 API 执行此操作时(例如,我尝试编写自己的模态循环),主应用程序的窗口不会重绘所有元素:它重绘标准元素,但不是客户区。无模式对话框显示得很好。

我怀疑发生这种情况是因为 MFC 并没有真正意义上的 Win32 模式对话框。它只能有一个消息循环,DialogBox() 中的一个单独循环会破坏其微妙的机制。这是解释这一点的a CodeProject article。但是这篇 CodeProject 文章已有 9 年的历史,所以从那时起情况可能发生了变化。有人可以对此有所了解吗?该应用使用 MFC 8(即mfc80.dll)。

更新。这是original question的链接;它可能包含一些附加信息。

更新 2。感谢大家;我真的很感激所有的建议,它肯定有助于我了解事物如何组合在一起。我要探索的第一条路径是使用本机 MFC 的“模态”对话框。 (由于我使用 Python 完成所有这些操作,因此我将使用 Python 绑定 MFC,pywin32)。这需要一些时间;准备好后,我会用结果更新帖子。

【问题讨论】:

  • +1 好问题,我有兴趣看到答案!
  • 另见*.com/questions/5058929,此问题是后续问题(或多或少)。
  • 能否请您使用 Spy++(Visual Studio 自带)或其他类似的应用程序(我知道可以在 catch22.net/software/winspy 找到)来查看“控制台”窗口的客户区是否是不止一个子窗口?!
  • @STATUS 有几个子窗口:顶部是一个粗的 XTPTooBbar,下面是一个 Dialog (#32770)(带有 'Layout' 的那个),然后还有两个滚动条和一个自定义它们之间的“成长箱”(此处不可见)。他们都正确地重绘。没有其他子窗口。没有重绘的是“控制台”窗口的客户区。

标签: winapi mfc modal-dialog


【解决方案1】:

每个线程都可以有一个消息循环。将您的模态对话框放入一个单独的线程中,并通过禁用父窗口来模拟 Windows 的标准行为。

编辑:经过一些讨论(见下文),父代码的行为似乎不正确。

不过,我认为有可能的解决方法。一个可能是覆盖错误窗口内容的父窗口(对于模式对话框,但对于当前行为不正确的窗口),但从内存中的 DC 重新绘制它以模仿正确的行为。当然,父窗口仍然必须被禁用。另一种解决方案可能是对父窗口进行子类化,以纠正行为。由于插件将在同一进程中运行,因此实现应该很简单。

【讨论】:

  • 这不太可能工作,因为这个插件是由宿主应用程序同步调用的。
  • @David Heffernan:对,基于原始问题的哪一部分?此外,主机应用程序是否同步调用它无关紧要,因为可以编写插件以阻塞其调用(如主机应用程序所期望的那样),直到包含消息循环的线程(并且确实所有对话工作)退出。
  • @STATUS 基于这样一个事实,即它必须在主循环中阻塞,主应用程序才能重绘失败。
  • @David Heffernan:所以你所说的实际上是应用程序根本无法正常运行(或者,换句话说:不支持真正的“模态插件”)。因为对DialogBox() 确实 的调用实际上禁用了父级(如我所写),并且禁用的父级不需要重绘(Windows 正在完成所需的任何操作)。此外,通过让“适当的”窗口显示父客户区域的已保存画布,仍然可以使用额外的线程模拟此行为。在任何其他情况下,RCE 始终是一种选择,可以在应用程序本身内部转动正确的杠杆。
  • @STATUS 我相信 OP 已经尝试过使用 parent = NULL。看看他之前的问题。
最近更新 更多