delphi XE-5跨平台开发 - 调用showmodal表单

时间:2014-03-05 20:35:03

标签: delphi firemonkey delphi-xe5

我目前正在使用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)。不确定为什么?

1 个答案:

答案 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;