Reputation: 1368
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
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
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