Wrong form focused after form close in firemonkey

When showing and closing forms in firemonkey, the application cannot remember which form was the last activated form and activates the wrong form.

How can I activate the last active form instead of the freeform selected by the application?

Replicate: create 3 forms and open each one in turn from the previous form.

I mainform and 2 ChildForms, the second form is the parent of the third form.

I am opening the first childForm from my MainForm.

var
  tmpForm2:TForm2;
begin
  tmpForm2:=TForm2.Create(self);
  tmpForm2.Show;
end;

      

This Form has a button that shows the second child form

var
  form3:Tform3;
begin
  form3:=TForm3.Create(nil);
  form3.Show;
end;

      

When I open the second ChildForm and close it, the Mainform is activated . Instead of the first ChildForm

Now I repeat this process, but closing the second ChildForm activates the first as you would expect.

Next time the Mainform is activated again, so the order keeps chainging instead of the real active active form.

+3


source to share


2 answers


Looks like it was a bug in Delphi XE7 / XE7 Update 1 in function

TScreen.NextActiveForm function (const OldActiveForm: TCommonCustomForm): TCommonCustomForm;

In Delphi XE8 this function works correctly and you will be returned to the previous window.



In XE8, they rewrite the function TScreen.NextActiveForm (const OldActiveForm: TCommonCustomForm): TCommonCustomForm;

Dog nail for XE7. I am copying a function from XE8 and using it in front of a closed form. I only tested it under Windows platform.

unit ufmForm3;

interface

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

type
  TfmForm3 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
    function NextActiveForm(const OldActiveForm: TCommonCustomForm): TCommonCustomForm;
  end;

var
  fmForm3: TfmForm3;

implementation

{$R *.fmx}

procedure TfmForm3.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  NextActiveForm(Self);
end;

function TfmForm3.NextActiveForm(const OldActiveForm: TCommonCustomForm): TCommonCustomForm;
var
  I, CurrIndex: integer;
begin
  Result := nil;
  CurrIndex := Screen.IndexFormOfObject(OldActiveForm);
  if CurrIndex >= 0 then
  begin
    I := CurrIndex - 1;
    while (I >= 0) and (Screen.Forms[I].Released or not Screen.Forms[I].Visible) do
      Dec(I);
    if I < 0 then
    begin
      I := Screen.FormCount - 1;
      while (I >= 0) and (I <> CurrIndex) and (Screen.Forms[I].Released or not Screen.Forms[I].Visible) do
        Dec(I);
    end;
    if (I >= 0) and (I <> CurrIndex) then
    begin
      Result := Screen.Forms[I];
      Screen.ActiveForm := Result;
    end;
  end;
end;


end.

      

+2


source


I had a related issue in Delphi FMX Berlin. My SDI application has a hidden "real" main form and one or more instances of a work form. When one of the working forms was called a modal dialog, I found that when the dialog was closed, the focus was on the form other than the calling form. The solution turned out to be simple.

(1) Create a dialogue with the owner Self:

MyDlg := TMyDlg.Create(Self);
MyDlg.ShowModal;

      



(2) Use the following in the OnClose modal dialog:

procedure TMyDlg.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    Action := TCloseAction.caFree;
    Screen.ActiveForm:=TMySDIAppForm(Self.Owner);
end;

      

0


source







All Articles