FMX: модальные формы не остаются на вершине (Windows)

#delphi #firemonkey #delphi-10.4-sydney

#delphi #firemonkey #delphi-10.4-Сидней

Вопрос:

Есть несколько случаев, когда формы или диалоговые окна, которые должны быть модальными, не остаются на вершине. Я создаю для Windows, используя 10.4. Вот простой пример, включающий две формы и TSaveDialog.

Чтобы воспроизвести проблему:

  • Запустите приложение в Windows
  • Нажмите кнопку Показать окно (вы должны увидеть Form2)
  • Нажмите кнопку Показать диалоговое окно сохранения (вы должны увидеть диалоговое окно сохранения)
  • Щелкните другое окно, которое не является частью приложения, например окно проводника
  • Нажмите Form2. Form1 теперь будет впереди

Если вы повторите это, но сначала увеличите Form1, пользователю будет нелегко решить, не закрыв программу из диспетчера задач или не используя некоторые экспертные знания Windows.

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
 

Блок1:

 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.
 

Блок2:

 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.
 

Я не видел такого поведения в приложениях VCL (модальные окна всегда остаются на вершине). Я также видел проблему в приложениях FMX с формами, которые были показаны с помощью ShowModal и даже окон сообщений, созданных с помощью ShowMessage. Использование TDialogServiceSync.ShowMessage, похоже, помогает предотвратить это, но даже тогда некоторые пользователи сталкиваются с той же проблемой.

Почему это происходит и могу ли я что-нибудь сделать, чтобы это исправить?

Ответ №1:

Попробуйте установить родительский элемент.

Нравится :

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

Я получил хороший результат с этим, но в OSX это не работает.

Комментарии:

1. Спасибо. По крайней мере, это помогает в моем примере.

Ответ №2:

Вы могли бы установить FormStyle Form2 значение StayOnTop

FormStyle — это одно из значений Normal, Popup или StayOnTop, определенных в TFormStyle.

Обычный: обычная форма. Такая форма может иметь активное состояние и поддерживать z-порядок.

Всплывающее окно: такая форма не может быть активной. Все формы этого типа принадлежат списку PopupForms.

StayOnTop: эта форма остается поверх рабочего стола и других форм в приложении, за исключением любой другой формы, для которой также установлен FormStyle в StayOnTop. Если одна форма StayOnTop запускает другую, ни одна из форм не будет постоянно оставаться на вершине.

https://docwiki.embarcadero.com/Libraries/Sydney/en/FMX.Types .TFormStyle

Комментарии:

1. Я согласен с Басом ван дер Линденом . Отображение формы модально не означает, что она останется на вершине. Вам нужно установить значение FormStyle быть StayOnTop первым. Теперь, поскольку диалоги также являются просто модальными формами, необязательно, чтобы диалоговая форма оставалась поверх другой модальной формы. В VCL вы можете передать дополнительный параметр в диалоговое окно, указав ему, какая из его родительских форм всегда остается над ним. Но, к сожалению, в FMX такой опции нет

2. В этом проблема. TSaveDialog не имеет свойства FormStyle.

3. Проблема с этим ответом заключается в том, что я, возможно, не хочу, чтобы Form2 всегда оставался на вершине. Возможно, я захочу отобразить обе формы и переключаться между ними. Но когда отображается диалоговое окно сохранения, я ожидаю, что оно всегда будет оставаться на вершине. К сожалению, для TSaveDialog нет свойства FormStyle. Однако ответ Эдвардса решает эту проблему.