1

While adding a secondary window (TForm) to a project written with Embarcadero C++Builder 10.4, I have the problem where that secondary window is always in front of the main one. That is, when clicking on the primary window, the secondary window loses focus but remains on top of the primary window.

I have tried changing the BorderStyle property, the PopupMode property, and I even tried to call the secondary window's SendToBack() method when the primary window activates. Nothing changes.

The secondary window is created with a NULL owner, and it is shown through it's Show() method.

The question is simple: How can I make the active window (TForm) on top of the other windows (TForm)?

Primary window behind secondary (Primary TForm should not be behind secondary TForm when primary is active.)

Yanick Rochon
  • 51,409
  • 25
  • 133
  • 214
  • There is WinAPI function, SetForegroundWindow, call it on the primary window – armagedescu Jan 12 '23 at 19:28
  • That's a good suggestion, alas it does not work :( – Yanick Rochon Jan 12 '23 at 19:32
  • Just a guess, see if you call it on a child window. It must be the topmost parent, or frame window if is mdi. Also it will not work if secondary is shown modally. There is a discussion about setting the foreground window https://stackoverflow.com/questions/1463417/what-is-the-right-way-to-bring-a-windows-forms-application-to-the-foreground – armagedescu Jan 12 '23 at 19:41

1 Answers1

3

This is expected behavior.

With Application->MainFormOnTaskBar set to true, when the secondary TForm is creating its window, and that Form's FormStyle is fsNormal, and the Form is not being shown modal, then its PopupMode is ignored and its owner window (in Win32 API terms, not VCL terms) gets set to the Application->MainForm window.

When a window has an owner window assigned, it can't ever go behind its owner.

To do what you are asking for (without switching to an MDI design), you need to instead have the hidden TApplication window be the owner of your secondary window, then you will be able to freely switch between your two windows. To accomplish that, you can either:

  • set Application->MainFormOnTaskBar to false (not advisable on Vista+ systems, as it will also disable a lot of other VCL behaviors that are needed for proper Vista+ interactions)

  • use the TApplication::OnGetMainFormHandle event to provide the desired owner window, in this case Application->Handle

  • have the secondary TForm class override the virtual CreateParams() method and set Params.WndParent to Application->Handle.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thank you for that information. For the second option, when and how many times is the event `TApplication::OnGetMainFormHandle` invoked? Same thing with the third option: when should `Application->Handle` be set, and is that applicable for multiple secondary windows? – Yanick Rochon Jan 12 '23 at 20:44
  • "*when and how many times is the event TApplication::OnGetMainFormHandle invoked?*" - any time the `TApplication::MainFormHandle` property is read. Look at the VCL's source code to find all the places, but I do know it happens during `TForm` window creation, and various dialog box activations (usually if `Application->ModalPopupMode` is `pmNone` or `Application->ActiveFormHandle` is null). "*Same thing with the third option*" - whenever the Form's `HWND` is (re)created. "*when should `Application->Handle` be set*" - whenever you don't want a Form's window to depend on another Form's window. – Remy Lebeau Jan 12 '23 at 21:02