The main form of the Delphi application moves behind other windows on modal closure

I am having problems with the fact that my main form disappears outside the windows of other applications when closing modal forms, and I was hoping that someone would encounter this problem (and solve!) Earlier or suggest where to find breakpoints for debugging the problem.

My problems initially began with the classic problem of "shy dialogue" with modal dialogs appearing in the main form, which arose intermittently. To sort this out, I changed all my popupmode modal forms to pmAuto , and also added Application.ModalPopupMode := pmAuto; and Application.MainFormOnTaskBar := true; to my dpr application.

Now I get that the main form disappears behind other windows when closing modal popups. I suspect that the behavior is mainly caused by the fact that the modal form opens a second window (I have problems with MessageDlg and direct Form.create(Application); Form.show; ), although there are no obvious problems with show / free code (ShowModal forms are created owner = nil, modess with owner = application). In both cases, the form disappears when the first original modal form is closed, but manipulating the modal form without starting a new form / dialog seems to work as expected.

In the background, on the main form, there are other nasty things with an update timer that activates the background thread, but usually it does not work at a time when it is required that it does not work. In addition, we make calls to the remote server through a third-party DLL (the application is actually a client GUI).

Annoyingly, I cannot get a behavioral simulator, and working in the IDE makes it difficult to monitor the behavior, since the IDE itself contains many windows that mutate the Z-order.

Change After writing my answer below, I get a deactivated event sent to the application (I can catch it through Application.OnDeactivate) - similar to WPF. The application completely loses focus on closing the window . There is no activation method in Delphi that has C # solutions, but I will play with some messages on Windows to find out if I can get anywhere

+6
source share
1 answer

Following David's recommendations in the comments, I created a small registration form that will be created at startup, containing a memo, timer, and the following OnTimer event:

 procedure TForm1.Timer1Timer(Sender: TObject); function logtomemo(aHandle: HWND): TWinControl; var form: TWinControl; begin form := findControl(ahandle); if form <> nil then memo1.Lines.Add(format('handle %d - form %s', [ahandle, form.Name])); result := form; end; var handle: HWND; form: TWinControl; begin memo1.Clear; handle := application.ActiveFormHandle; repeat form := logtomemo(handle); handle := GetWindow(handle, GW_OWNER); until (handle = application.MainFormHandle) or (form = nil); logtomemo(handle); end; 

By clicking on the button, I noticed that as soon as I clicked outside of my application, our splash shape appeared as the only form on the list. (Historically, our splash screen was used only to release after Application.Run, because they used some other links on it for some reason - they are no longer needed until my time).

Changing the lifetime of the pop-up screen, which should be destroyed before Application.Run, seems to have sorted out the problem - something that I would never have guessed would have been the cause in a million years.

I need final confirmation that it will not appear again when I get rid of this small form of debugging, but I hope the problem that upset me for several days is now sorted - thanks!

Edit

As I already noted in my editing and comments on this question, the above debug file did not work, as the presence of a new form “fixed” the problem. Changing the code so that the output was sent to the event log or text file, rather than requiring a form, also did not find anything - all forms in order Z remained in place.

In the end, I was able to fix the symptom, not the cause, by adding the following code to Application.OnModalEnd

 if Application.ModalLevel = 0 then Windows.SetActiveWindow(Application.MainFormHandle); 

This successfully returns the active window to the main form after closing the last modal dialog.

This can have some side effects if the user expects a modeless form that is not the main form for focus recovery, but our application architecture really does not match this structure and Application.MainFormOnTaskbar , the main form will not hide other forms (if they are not uneven)

+5
source

All Articles