我目前正在使用Delphi XE-5在我的Windows桌面上开发跨平台应用程序。我有一个我想用于跨平台开发的单元(对于这个例子,我们可以使用Windows和Android)。
在我的Windows和Android应用程序中,我都有一个带有以下onClick事件的按钮
procedure TfrmMain.Button1Click(Sender: TObject);
begin
LPSystem:= TLPSystem.Create;
try
if LPSystem.execute then
begin
ShowMessage('Logged in!');
end
else
ShowMessage('Not logged in!');
finally
LPSystem.Free;
end;
end;
在下面的执行例程中,向用户显示ShowModal对话框(根据平台的不同形式)
function TLPSystem.execute: Boolean;
var
{$IFDEF MSWINDOWS}
frmLoginW: TfrmLoginW;
{$ENDIF MSWINDOWS}
{$IFDEF Android}
zResult: Boolean;
frmLoginM: TfrmLoginM;
{$ENDIF Android}
begin
result:= False;
{$IFDEF MSWINDOWS}
frmLoginW:= TfrmLoginW.Create(nil);
if frmLoginW.ShowModal = mrOK then
begin
{$ENDIF MSWINDOWS}
{$IFDEF Android}
frmLoginM:= TfrmLoginM.Create(nil);
frmLoginM.ShowModal (procedure(ModalResult: TModalResult)
begin
if ModalResult = mrOK then
begin
{$ENDIF Android}
{$IFDEF MSWINDOWS}
end;
frmLoginW.Free;
{$ENDIF MSWINDOWS}
{$IFDEF Android}
end;
end);
if zResult then result:= zResult;
frmLoginM.Free;
{$ENDIF Android}
end;
这适用于Windows,但在Android上,我得到模态对话框之前得到了我的结果(即showmessage)。不确定为什么?
答案 0 :(得分:4)
带走你的IFDEF
陈述并查看你实际在做什么:
视窗:
function TLPSystem.execute: Boolean;
var
frmLoginW: TfrmLoginW;
begin
Result := False;
frmLoginW := TfrmLoginW.Create(nil);
if frmLoginW.ShowModal = mrOK then
begin
end;
frmLoginW.Free;
end;
这在功能上是正常的(虽然它没有根据对话框的Result
分配ModalResult
)。
机器人:
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;
这不遵循Embarcadero文档中列出的规则:
ShowModal Dialogs in FireMonkey Mobile Apps
更糟糕的是,采用匿名过程的ShowModal()
的重载版本以异步方式运行,因此在关闭模式窗体之前,Execute()
将退出。在退出之前它不能在表格上等待。所以你必须重新设计你的代码来处理它。
尝试更像这样的事情:
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;
或者,您可以使用ARC try/finally
摆脱Windows上的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;