德尔福 - 我如何找出哪个模态对话框的重点放在前面? [英] Delphi - how do I find out which modal dialog has focus and bring it to the front?
问题描述
我有一个Delphi 2006应用程序,可以弹出一个模态对话框来响应错误条件。似乎让自己进入一个这样的状态,其中一个模态对话是开放的,位于主窗体的前面,但两个窗体都不响应消息。点击或者给出一个bonk。该应用程序运行正常,UI正在更新主窗体,但您不能做任何事情。我想可能是主要形式下的另一个模态对话框。无论是我的一个还是Windows中的一个,我都不知道。
其他要点:
- 该应用程序响应键盘快捷键确定。其中一个这样的短路程序优雅地关闭应用程序,这样做有效。我自此以来一直无法重现这种情况。
- 该应用有一个托盘图标。这会响应鼠标右键点击。如果我从这里最小化应用程序,主窗体最小化并保留模式对话框显示,仍然没有焦点。如果我恢复了主要的形式,事情就是这样,既没有窗口有焦点。 Alt-tab具有类似的结果。
- 平台是Windows 7
- 在任何表单创建之前,我调用DisableProcessWindowsGhosting
-
与
ModalDialog.PopupParent:= MainForm;
ModalDialog.ShowModal;
-
如果其他模式对话框打开,我推迟了这些错误对话框:
if(Application.ModalLevel = 0)then
{open modal dialog}
我的问题有两个部分:
是否以编程方式发现什么窗口有焦点?我可以为这种情况采取一些行动,或者最后的手段,我们可以提供一个快捷键,将其带到前面或采取一些回避行动(取决于对话框),如将ModalResult设置为mrCancel。
如何发生这种情况?通常当我在主窗体后面得到一个模态对话框(我可以通过获取模态对话框打开,最小化托盘图标的应用程序,然后再次恢复应用程序 - 应用程序主窗体在对话框前面恢复,对话框仍然保留焦点),我可以通过点击托盘图标将其重新放在前面,或者使用 Esc
键关闭它,但是在此不起作用
**更新* * b
Misha的修复工作与非delphi对话框(如TSaveDialog)相去甚远。在调用执行之前添加
Application.ModalPopupMode:= pmAuto;
也可以让他们工作。 >。
通过让它工作我的意思是保存对话框按照以下顺序在前面:
而不是 ModalPopupMode:= pmAuto
的主窗体后面。
所以我希望这些更改将有助于(至今未被再现)的问题。
最后一个活动的弹出窗口(VCL或否)可以使用 GetLastActivePopup
:
function GetTopWindow:HWND;
begin
结果:= GetLastActivePopup(Application.Handle);
if(Result = 0)或(Result = Application.Handle)或
不是IsWindowVisible(Result)then
结果:= Screen.ActiveCustomForm.Handle;
结束
这是从 TApplication.BringToFront
。
将此窗口放在前面可以通过 SetForegroundWindow
:
SetForegroundWindow(GetTopWindow);
请注意, Application.BringToFront
可能会但是我一度体验到它没有正常运作,这种情况我从来没有能够再现。
I have a Delphi 2006 app which can pop up a modal dialog in response to an error condition. It seems to get itself into a state where one of these modal dialogs is open, positioned in front of the main form, but neither form is responding to messages. Clicking on either gives a "bonk". The app is running fine, the UI is updating the main form, but you can't do anything. I guess there is most likely another modal dialog under the main form. Whether it is one of mine or one from Windows I have no idea.
Other points:
- the app responds to keyboard shortcuts OK. One of these shortuts shuts down the app gracefully and this worked. I have been unable to reproduce the situation since.
- the app has a tray icon. This responds to right mouse clicks. If I minimize the app from here the main form minimizes and leaves the modal dialog displayed, still without focus. If I restore the main form, things are as they were, with neither window having focus. Alt-tab has similar results.
- platform is Windows 7
- I call DisableProcessWindowsGhosting before any forms are created
I open the modal dialogs with
ModalDialog.PopupParent := MainForm ; ModalDialog.ShowModal ;
I postpone these error dialogs if other modal dialogs are open:
if (Application.ModalLevel = 0) then {open modal dialog}
My question has two parts:
Is there a way of programmatically finding out what window has focus? I could then take some action for this scenario or a last resort I could them provide a shortcut key to bring it to the front or take some evasive action (depending on the dialog) like set the ModalResult to mrCancel.
How can this situation arise? Normally when I get a modal dialog behind the main form (I can do that by getting the modal dialog to open, minimizing the app from the tray icon, then restoring the app again - the app main form restores in front of the dialog, with the dialog still retaining focus), I can bring it to the front again by clicking on the tray icon, or close it with the Esc
key but it didn't work in this case.
**UPDATE**
Misha's fix worked apart from non-delphi dialogs like TSaveDialog. I was able to get them to work as well by adding Application.ModalPopupMode := pmAuto ;
just before the call to Execute
.
By "got it to work" I mean that the save dialog was in front after the following sequence:
- open save dialog
- minimize app from tray icon
- restore app from tray icon
whereas it was behind the main form without the ModalPopupMode := pmAuto
.
So I'm hoping these changes will help the (as yet unreproduced) problem.
The last active popup window (VCL or not) can be queried with GetLastActivePopup
:
function GetTopWindow: HWND;
begin
Result := GetLastActivePopup(Application.Handle);
if (Result = 0) or (Result = Application.Handle) or
not IsWindowVisible(Result) then
Result := Screen.ActiveCustomForm.Handle;
end;
This is somewhat copied from TApplication.BringToFront
.
Bringing this window to the front can be done by SetForegroundWindow
:
SetForegroundWindow(GetTopWindow);
Note that Application.BringToFront
might do the trick altogether, but I once experienced it did not function properly, a situation I have not been able to reproduce since though.
这篇关于德尔福 - 我如何找出哪个模态对话框的重点放在前面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!