I am working on Delphi 11.2 with an older Delphi project, pre Application.MainFormOnTaskBar's introduction, so by default it was set to False. I tried adding the following line to the project's .dpr file after Application.Initialize; like the Delphi documentation suggests:
Application.MainFormOnTaskBar := True;
My goal was to mimic every other modern Windows application and show a preview of the current MainView on the Windows taskbar. While my change did achieve this, it also resulted in undesirable behavior with modal dialogs.
The logic for determining modal dialogs' parents and window z-order differs from an application that has Application.MainFormOnTaskBar := False;. This now frequently shows modal dialogs behind other floating windows in the application, making the modal dialogs unclickable and locking up the application.
Many others have seen the same behavior, and it is noted in Delphi's documentation. Unfortunately, the most helpful information that I could find about getting the old z-ordering back had dead links, as it was from 2007/2008 around when Application.MainFormOnTaskBar was introduced. The older forum posts point to using PopupParent, PopupMode and Application.ModalPopupMode to reproduce the older modal dialog behavior. I have not had any success with those.
One workaround that I found to work was setting Params.WndParent := 0; in a Form's CreateParams(). However, I would prefer to find a universal solution for all modal dialogs, as I use built-in VCL methods like ShowMessage() and the System object TMsgDlgType to display simple modal dialogs.
I would like to have the old modal dialog z-ordering and have the live MainView preview appear on the Windows taskbar. Is there a new best way to achieve this? Have there been any advancements with this feature since its introduction? Can I show the live MainView preview on the Windows taskbar without setting Application.MainFormOnTaskBar?
EDIT:
Here is some more information about the overall flow of the project with Application.MainFormOnTask := False;.
I start by showing a login form, which is a custom form inheriting from TForm, by calling LoginForm.ShowModal(). The Windows taskbar icon appears for the project and the preview shows the login form. The preview stays updated as information is entered. Once information is entered, I proceed to show another custom 'TForm' while things are being created in the background. This is also reflected in the Windows task bar preview. Once creation is complete I show the MainView. The taskbar now shows the login form as the taskbar preview even though it is no longer present anywhere on the screen. Then I show other popup custom forms by calling one of the two functions below depending on if I want it to be modal or not.
// Set form to stay on top
SetWindowPos(Self.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOSENDCHANGING);
Self.Show();
// Set form to stay on top
SetWindowPos(Self.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOSENDCHANGING);
Result := Self.ShowModal();
Things are slightly different when Application.MainFormOnTask := True;. I show the login and creation forms same as before. However, the taskbar icon does not appear until the MainView is shown. Throughout its runtime the preview stays updated. However, when showing modal forms the z-ordering will be behind those forms which are not modal, using the methods above.
In the hope this helps someone, I have found the only reliable way to have your modal forms appear above a
StayOnTopform is to set thePopupModeimmediately before callingShowModal.You can easily recreate the issue whereby Modal forms appear behind a
StayOnTopform by creating a new Delphi 11 application that has two forms, Form1 (FormStyle := fsStayOnTop;) and Form2 containing aTComboBoxand a public method,SetEnvironment.Form2
SetEnvironmentsimply clears theTComboBox.Items:Form1 has
FormStyle := fsStayOnTopand has a single button which shows Form2 modally:If you comment out
ComboBox1.Items.Clearin Form2 then the order of settingPopupModedoesn't matter, Form2 is always displayed above Form1.