r_j
r_j

Reputation: 1368

Wrong Form is focused after closing form in firemonkey

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

How can I activate the last active form instead of an arbitrary form chosen by the application?

To replicate : Create 3 forms and open each one in succession from previous form.

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

I open the first childForm from my MainForm.

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

In this Form there is a button that shows second childform

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 the process but when closing the second ChildForm, the first one is actived, as one would expect.

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

Upvotes: 3

Views: 1343

Answers (2)

Duns
Duns

Reputation: 438

I had a related problem in Delphi FMX Berlin. My SDI application has a hidden "real" main form and one or more instances of the working form. When one of the working forms called a modal dialog, I was finding that on closure of the dialog, the focus was going to a form different to the calling form. The solution turned out to be simple.

(1) Create the dialog with owner Self:

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

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

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

Upvotes: 0

Zam
Zam

Reputation: 2940

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

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

On Delphi XE8 this function works correctly and you return to previous window.

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

Dog-nail for XE7. I copy function from XE8 and using it before close form. I tested it only 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.

Upvotes: 2

Related Questions