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.
source to share
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.
source to share
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;
source to share