Closing the modal form (s) from the outside and opening a new modal form

In my main form, I have a button that opens a modal Form2(which can open other modal forms). before opening Form2I set a timer that programmatically closes all active modal forms ( Form2.Close) and opens a new modal Form3.

The problem is that when it Form3opens modally, it Form2remains (visible) and only when I close Form3, clicking Xwill Form2close.

To play, add 3 forms to the project, add TButtonand lower TTimerto Form1(main form):

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
  public
  end;

var
  Form1: TForm1;

implementation

uses Unit2, Unit3;

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Timer1.Enabled := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Timer1.Enabled := True;
  with TForm2.Create(Application) do
  try
    ShowModal;
  finally
    Free;
  end;
end;

procedure CloseActiveModalForms;
var
  I: Integer;
  F: TCustomForm;
  L: TList; // list of modal forms
begin
  L := TList.Create;
  try
    for I := 0 to Screen.CustomFormCount - 1 do
    begin
      F := Screen.CustomForms[I];
      if (fsModal in F.FormState) then
        L.Add(F);
    end;
    for I := 0 to L.Count - 1 do
      TCustomForm(L.Items[I]).Close; // this sets ModalResult := mrCancel
  finally
    L.Free;
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  CloseActiveModalForms; // this should close TForm2 but it does not.

  with TForm3.Create(Application) do // create new Modal TForm3
  try
    ShowModal;
  finally
    Free;
  end; 
end;

end.

Form2 ? Form2 CloseActiveModalForms?

+4
1

:

1 Form1.Button1Click
2 Form2.ShowModal //Local message processing loop until form closes
3 Form1.Timer1Timer //Here you attempt to close the form
                    //but it doesn't actually until ShowModal exits
4 Form3.ShowModal // Another message loop that doesn't return until form closes

, 2 Form3. , ShowModal . Show Form3 (.. ShowModal), , , Form2 , .


, , Form3 , Form2 . OnFormDestroyEvent ( , ).

procedure TForm1.ShowForm3(Sender: TObject);
var
  LForm: TForm;
begin
  LForm := TForm3.Create(Application); //as you created it, but nil owner should suffice
  try
    LForm.ShowModal;
  finally
    LForm.Free;
  end; 
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  //You will need to figure out how you reference the Form2 instance.
  Form2.OnFormDestroy := ShowForm3;
  CloseActiveModalForms;
  //Form2 will close after you backtrack up the call-stack.
  //When it destroyed, your event handler will create and show a TForm3 instance.
end;

, . .

, .

+5

Source: https://habr.com/ru/post/1660930/


All Articles