Alex Rivera | Logout

Delphi - how do I find out which modal dialog has focus and bring it to the front?

Asked 2012-03-21T19:59:20.000
9

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

Edit
Report

1 Answer

5

If a form that has focus takes too long to respond to messages (Form1), so that Windows thinks Form1 is unresponsive, and Form1 then displays a modal form (Form2), after Form2 is displayed and the application is processing messages again, Form1 will be brought to the front, thereby potentially "covering" Form2.

Putting this in the Application.OnIdle event will do the trick:

  if Assigned(Screen.ActiveForm) then
  begin
    if (fsModal in Screen.ActiveForm.FormState) and
       (Application.DialogHandle <= 0)) then 
    begin
      Screen.ActiveForm.BringToFront;
    end;
  end;
answered 2012-03-22T01:43:38.163

Your Answer