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

delphi XE-5跨平台开发-调用showmodal表单,delphi,firemonkey,delphi-xe5,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

我目前正在使用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对话框(根据平台的不同形式)


这对windows非常有效,但在Android上,我在获得模式对话框之前会得到结果(即showmessage)。不知道为什么?

拿走你的
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;
这在功能上是正常的(尽管它没有根据对话框的
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文件中概述的规则:

更糟糕的是,采用匿名过程的重载版本
showmodel()
会异步运行,因此您的
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;

或者,您可以通过使用ARC
界面来摆脱Windows上的
try/finally

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;


拿走你的
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;
这在功能上是正常的(尽管它没有根据对话框的
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文件中概述的规则:

更糟糕的是,采用匿名过程的重载版本
showmodel()
会异步运行,因此您的
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;

或者,您可以通过使用ARC
界面来摆脱Windows上的
try/finally

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;


在这个链接中看看ShowModal是如何在Android上完成的:@sencent-我相信这就是我正在使用的-除了DisposeOf method看看ShowModal是如何在Android上完成的:@sencent-我相信这就是我正在使用的-除了DisposeOf method抱歉,但是这个例程不适用于windows或Android!这里没有实例化frmLoginW(Windows对话框窗体)的地方,只有android窗体(frmLoginM)。我相信每个对象在各自的ifdef中都应该有一个var。对于android部分,它会在显示对话框之前显示结果——就像我发布的另一个问题和你发布的答案一样。另一方面,通过添加for实例化代码并将其放置在适当的IFDEFYour right中,我可以编辑代码并使windows版本正常工作。我甚至不能在主窗体侧使用它们。如果我去掉了那里的ShowMessages,那么模态形式会首先显示出来。我不明白为什么会这样,但我想我可以将就一下。@LuvRAD:frmLoginW
很好,我甚至没有注意到这两个平台使用不同的类类型。我已经调整了答案。
showmodel
在移动编译器上没有阻塞。最后一个示例在Android中不起作用,因为当execute退出时zResult未初始化。另外,
DisposeOf
调用也是错误的,因为当返回ModalResult时,匿名帧依赖于有效的对象。即使这是固定的,
showmodel
也不建议在移动编译器上使用。改为使用
Show
。我使用
showmodel()
更新了我的答案,以采用不同的方法。抱歉,此例程不适用于windows或android!这里没有实例化frmLoginW(Windows对话框窗体)的地方,只有android窗体(frmLoginM)。我相信每个对象在各自的ifdef中都应该有一个var。对于android部分,它会在显示对话框之前显示结果——就像我发布的另一个问题和你发布的答案一样。另一方面,通过添加for实例化代码并将其放置在适当的IFDEFYour right中,我可以编辑代码并使windows版本正常工作。我甚至不能在主窗体侧使用它们。如果我去掉了那里的ShowMessages,那么模态形式会首先显示出来。我不明白为什么会这样,但我想我可以将就一下。@LuvRAD:frmLoginW
很好,我甚至没有注意到这两个平台使用不同的类类型。我已经调整了答案。
showmodel
在移动编译器上没有阻塞。最后一个示例在Android中不起作用,因为当execute退出时zResult未初始化。另外,
DisposeOf
调用也是错误的,因为当返回ModalResult时,匿名帧依赖于有效的对象。即使这是固定的,
showmodel
也不建议在移动编译器上使用。改为使用
Show
。我使用
showmodel()
更新了我的答案,以采用不同的方法。
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;