3422 Old Capitol Trail – Suite 1125, Wilmington – DE 19808, United States

Keep child windows in front!

    Review Thinfinity VirtualUI

    New here? Read more about why software developers are adopting Thinfinity VirtualUI to increase the value of their Windows applications.

 
VirtualUI: keep child windows in front!Early this year, we shared an article about a Delphi error. As we explained there, this error happens when the Application.MainFormOnTaskBar property is set to False and an application main form is minimized. When this happens the window gets hidden, but it has no way to be restored.

We also found a similar behavior in applications where child windows —modal or modeless— were drawn or hidden behind the main window; and not in front, as expected. We know that this can happen under certain circumstances when the project has the Application.MainFormOnTaskBar property set to False. This seems to suggest that Delphi could be the culprit.

 

Why the error occurs?

All programs send messages to the operative system. Some messages indicate a change in the window “z” order, which defines which form is in the front, and which forms are behind.

When the Application.MainFormOnTaskBar property is set to false, all forms —modal and modeless— are siblings of the mainform. They all share the application window as common parent. Being all siblings, all of them have the chance to go behind the other.

At some point during the display of a modal form, a WM_WINDOWPOSCHANGED message is sent to the mainform, moving it to the top.

 

How to fix the error and keep the child windows in front

The best solution is to set the Application.MainformOnTaskbar property to True right after the Application.CreateForm statement.

 

program KeepInFrontExample;
uses
  Forms,
  VirtualUI_AutoRun,
  MainForm in 'MainForm.pas' {FormMain};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TFormMain, FormMain);
  Application.MainFormOnTaskbar := True;
  Application.Run;
end.

 

In this way, Delphi will set the mainform as parent of all the other forms. This workaround leaves no way for any form to go behind the mainform, as it would be their parent element.

That is how you can make sure child windows are always in front of the mainform.

Other functions to bring child windows to top

Need help to activate an inactive child window with the bring the window.open() window on front function?
Other languages apply the BringWindowToTop function, but what if BringWindowToTop doesn’t work?
If you need help with C++ or C# examples, contact us.
 

Related Posts

Comments (6)

Solution provided does not work. Sorry.

This worked for me : add

Application.ModalPopupMode := pmAuto;

in the .dpr after Application.Initialize;

Hi Chris,
The solution proposed actually works with all Delphi forms. When you set Application.MainFormOnTaskbar := True, all the forms that Delphi creates are created with the Mainform as parent instead of TApplication, thus no other window can go behind the mainform because all depends on it.
Application.ModalPopupMode := pmAuto seems to act on common dialogs like OpenFileDialog, PageSetup, etc. which IMHO is complementary to the solution we provided and is actually a great find.
Thanks,
Gustavo RIcardi

Hi Gustavo,
We do not let delphi autocreate the forms in our app, there are too much form to let delphi cretae them all at startup, so we do this ourself manually. matbe we are missing something when whe do the create. What properties should we set ?

No matter when you create the form. If you look into the delphi source code, when Application.MainFormOnTaskbar is set to True you will see that every time you create a form, it automatically will set its parent to the MainForm.
You can verify this by creating two forms (at startup or later). If Application.MainFormOnTaskbar is True, you will never be able to change the z-order between both forms, you will see the mainform always behind. Then turn Application.MainFormOnTaskbar to false, and you now both forms can change the z-order. This is because in this case both share the same parent, TApplication.

The exception seems to be the common dialogs, where it uses the ActiveForm as parent when you set Application.ModalPopupMode to pmAuto.

So my recommendation is to use both, Application.MainFormOnTaskbar := true and Application.ModalPopupMode := pmAuto.

I found that both are required in the project setup to avoid Z-order issues that we have encountered. Thank you both for the great tips!

I agree, we are moving back to the desotkp application development approach with Javascript. From event-driven design to the MVC architecture, these applications are going to get more and more complex over time. Given that much of the interaction is request-response, it feels more like client-server programming with the added constraint of a stateless server. This means that many patterns common to client-server app development will begin to trickle back into the more complex JS-heavy applications.

Leave a comment