【发布时间】:2012-03-21 19:59:20
【问题描述】:
我有一个 Delphi 2006 应用程序,它可以弹出一个模式对话框以响应错误情况。它似乎进入了一种状态,其中一个模式对话框处于打开状态,位于主窗体的前面,但两个窗体都没有响应消息。单击任一都会给出“bonk”。应用程序运行良好,UI 正在更新主窗体,但您无能为力。我猜主窗体下很可能还有另一个模态对话框。我不知道是我的还是 Windows 的。
其他要点:
- 应用程序响应键盘快捷键 OK。其中一个快捷方式可以优雅地关闭应用程序,这很有效。从那以后,我一直无法重现这种情况。
- 应用程序有一个托盘图标。这响应鼠标右键单击。如果我从这里最小化应用程序,主窗体会最小化并显示模态对话框,但仍然没有焦点。如果我恢复主窗体,一切照旧,两个窗口都没有焦点。 Alt-tab 也有类似的结果。
- 平台是 Windows 7
- 我在创建任何表单之前调用 DisableProcessWindowsGhosting
-
我用
打开模态对话框ModalDialog.PopupParent := MainForm ; ModalDialog.ShowModal ; -
如果其他模式对话框打开,我会推迟这些错误对话框:
if (Application.ModalLevel = 0) then {open modal dialog}
我的问题分为两部分:
有没有办法以编程方式找出哪个窗口有焦点?然后我可以针对这种情况采取一些措施,或者作为最后的手段,我可以让他们提供一个快捷键将其置于最前面或采取一些规避措施(取决于对话框),例如将 ModalResult 设置为 mrCancel。
这种情况怎么会出现?通常,当我在主窗体后面得到一个模态对话框时(我可以通过打开模态对话框,从托盘图标最小化应用程序,然后再次恢复应用程序来做到这一点 - 应用程序主窗体恢复在对话框前面,使用对话框仍然保持焦点),我可以通过单击托盘图标再次将其置于前面,或者使用Esc 键将其关闭,但在这种情况下它不起作用。
**更新**
Misha 的修复与 TSaveDialog 等非 Delphi 对话框不同。通过在调用Execute 之前添加Application.ModalPopupMode := pmAuto ;,我也能够让它们正常工作。
“让它工作”是指保存对话框在以下序列之后:
- 打开保存对话框
- 从托盘图标最小化应用程序
- 从托盘图标恢复应用
而它位于没有ModalPopupMode := pmAuto 的主窗体后面。
所以我希望这些更改将有助于解决(尚未重现的)问题。
【问题讨论】:
-
找出哪个窗口有焦点并采取补救措施无济于事。你需要从源头上解决问题。这意味着了解窗口所有权(即 PopupParent)。
-
谢谢@David。找出哪个窗口有焦点肯定会有所帮助,因为它可能会告诉我如何重现问题,而我目前无法做到这一点。
-
一旦你有了它,你应该能够使用像 Spy++ 这样的东西来理解所有权关系。我会尝试从外部调试它,至少在你有重现之前。
-
您通常可以通过将 {$ifdef DEBUG}Sleep(5000);{endif} 添加到您的调试版本来使其重现 - 需要进行一些实验才能找到最“破坏性”的地方”。这个 z 顺序地狱的神奇触发因素是窗口认为您的应用程序没有响应。
标签: delphi delphi-2006