Search code examples
delphifiremonkeydelphi-10.4-sydney

FMX: Modal forms not staying on top (Windows)


There are several cases where forms or dialogs that should be modal are not staying on top. I'm building for Windows using 10.4. Here's a simple example involving two forms and a TSaveDialog.

To replicate the issue:

  • Run the application in Windows
  • Click the Show Window button (you should see Form2)
  • Click the Show Save Dialog button (you should see the save dialog)
  • Click another window that is not part of the application such as an Explorer window
  • Click Form2. Form1 will now be in front

If you repeat this but maximise Form1 first then it's not easy for the user to resolve without closing the program from Task Manager or using some expert windows knowledge.

Form1:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 480
  ClientWidth = 640
  Position = ScreenCenter
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object Button1: TButton
    Position.X = 264.000000000000000000
    Position.Y = 168.000000000000000000
    Size.Width = 97.000000000000000000
    Size.Height = 33.000000000000000000
    Size.PlatformDefault = False
    Text = 'Show Window'
    OnClick = Button1Click
  end
end

Form2:

object Form2: TForm2
  Left = 0
  Top = 0
  Caption = 'Form2'
  ClientHeight = 333
  ClientWidth = 489
  Position = ScreenCenter
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object Button1: TButton
    Position.X = 184.000000000000000000
    Position.Y = 136.000000000000000000
    Size.Width = 113.000000000000000000
    Size.Height = 41.000000000000000000
    Size.PlatformDefault = False
    Text = 'Show Save Dialog'
    OnClick = Button1Click
  end
  object SaveDialog1: TSaveDialog
    Left = 80
    Top = 40
  end
end

Unit1:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, Unit2,
  FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show;
end;

end.

Unit2:

unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    SaveDialog1: TSaveDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.fmx}

procedure TForm2.Button1Click(Sender: TObject);
begin
  SaveDialog1.Execute;
end;

end.

I have not seen this behaviour in VCL applications (modal windows always stay on top). I have also seen the issue in FMX applications with forms that have been shown using ShowModal and even message windows created with ShowMessage. Using TDialogServiceSync.ShowMessage seems to help prevent this but even then some users experience the same issue.

Why is this happening and is there anything I can do to fix it?


Solution

  • Try setting the parent.

    Like :

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Form2.parent := form1;
      Form2.Show;
    end;
    

    I got good result with this but in OSX it does not work.