德尔福 - 我如何找出哪个模态对话框的重点放在前面? [英] Delphi - how do I find out which modal dialog has focus and bring it to the front?

查看:141
本文介绍了德尔福 - 我如何找出哪个模态对话框的重点放在前面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆