Take away your IFDEF
statements and look at what you are actually doing:
Windows:
function TLPSystem.execute: Boolean;
var
frmLoginW: TfrmLoginW;
begin
Result := False;
frmLoginW := TfrmLoginW.Create(nil);
if frmLoginW.ShowModal = mrOK then
begin
end;
frmLoginW.Free;
end;
This is functionally OK (though it is not assigning the Result
based on the dialog's ModalResult
).
Android:
function TLPSystem.execute: Boolean;
var
zResult: Boolean;
frmLoginM: TfrmLoginM;
begin
Result := False;
frmLoginM := TfrmLoginM.Create(nil);
frmLoginM.ShowModal (
procedure(ModalResult: TModalResult)
begin
if ModalResult = mrOK then
begin
end;
end
);
if zResult then Result := zResult;
frmLoginM.Free;
end;
This is not following the rules outlined in Embarcadero's documentation:
ShowModal Dialogs in FireMonkey Mobile Apps
To make matters worse, the overloaded version of ShowModal()
that takes an anonymous procedure runs asynchronously, so your Execute()
would exit before the modal Form is closed. It cannot wait on the Form before exiting. So you will have to redesign your code to handle that.
Try something more like this:
type
TLPSystemLoginEvent = procedure(LoggedIn: Boolean) of object;
TLPSystem = class
private
procedure DoLoginResult(LoggedIn: Boolean);
public
OnLoginResult: TLPSystemLoginEvent;
procedure Execute;
end;
procedure TLPSystem.DoLoginResult(LoggedIn: Boolean);
begin
if Assigned(OnLoginResult) then OnLoginResult(LoggedIn);
end;
procedure TLPSystem.Execute;
var
{$IFDEF MSWINDOWS}
frmLoginW: TfrmLoginW;
{$ENDIF}
{$IFDEF Android}
frmLoginM: TfrmLoginM;
LSelf: TLPSystem;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
frmLoginW := TfrmLoginW.Create(nil);
try
DoLoginResult(frmLoginW.ShowModal = mrOK);
finally
frmLoginW.Free;
end;
{$ENDIF}
{$IFDEF Android}
frmLoginM := TfrmLoginM.Create(nil);
LSelf := Self;
frmLoginM.ShowModal(
procedure(ModalResult: TModalResult)
begin
LSelf.DoLoginResult(ModalResult = mrOK);
end
);
{$ENDIF}
end;
procedure TfrmLoginM.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := TCloseAction.caFree;
end;
procedure TfrmMain.Button1Click(Sender: TObject);
var
LPSystem: TLPSystem;
begin
LPSystem := TLPSystem.Create;
{$IFDEF MSWINDOWS}
try
{$ENDIF}
LPSystem.OnLoginResult := LoginResult;
LPSystem.Execute;
{$IFDEF MSWINDOWS}
finally
LPSystem.Free;
end;
{$ENDIF}
end;
procedure TfrmMain.LoginResult(LoggedIn: Boolean);
begin
if LoggedIn then
ShowMessage('Logged in!')
else
ShowMessage('Not logged in!');
end;
Alternatively, you can get rid of the try/finally
on Windows by utilizing an ARC interface
:
type
TLPSystemLoginEvent = procedure(LoggedIn: Boolean) of object;
ILPSystem = interface
procedure Execute;
end;
TLPSystem = class(TInterfacedObject, ILPSystem)
private
fOnLoginResult: TLPSystemLoginEvent;
procedure DoLoginResult(LoggedIn: Boolean);
public
constructor Create(ALoginResult: TLPSystemLoginEvent);
procedure Execute;
end;
constructor TLPSystem.Create(ALoginResult: TLPSystemLoginEvent);
begin
inherited Create;
fOnLoginResult := ALoginResult;
end;
procedure TLPSystem.DoLoginResult(LoggedIn: Boolean);
begin
if Assigned(fOnLoginResult) then fOnLoginResult(LoggedIn);
end;
procedure TLPSystem.Execute;
var
{$IFDEF MSWINDOWS}
frmLoginW: TfrmLoginW;
{$ENDIF}
{$IFDEF Android}
frmLoginM: TfrmLoginM;
LSelf: ILPSystem;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
frmLoginW := TfrmLoginW.Create(nil);
try
DoLoginResult(frmLoginW.ShowModal = mrOK);
finally
frmLoginW.Free;
end;
{$ENDIF}
{$IFDEF Android}
frmLoginM := TfrmLoginM.Create(nil);
LSelf := Self;
frmLoginM.ShowModal(
procedure(ModalResult: TModalResult)
begin
(LSelf as TLPSystem).DoLoginResult(ModalResult = mrOK);
end
);
{$ENDIF}
end;
procedure TfrmLoginM.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := TCloseAction.caFree;
end;
procedure TfrmMain.Button1Click(Sender: TObject);
var
LPSystem: ILPSystem;
begin
LPSystem := TLPSystem.Create(LoginResult);
LPSystem.Execute;
end;
procedure TfrmMain.LoginResult(LoggedIn: Boolean);
begin
if LoggedIn then
ShowMessage('Logged in!')
else
ShowMessage('Not logged in!');
end;