delphi XE-5跨平台开发-调用显示模式表单 [英] delphi XE-5 cross platform development - calling a showmodal form

查看:92
本文介绍了delphi XE-5跨平台开发-调用显示模式表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用Delphi XE-5在Windows桌面上开发跨平台应用程序。我有一个要用于跨平台开发的单元(在此示例中,仅允许在Windows和Android上使用)。

I am currently developing cross platform applications on my Windows desktop using Delphi XE-5. I have a unit I want to use for cross platform development (for this example, lets just work with Windows and Android).

在Windows和Android应用程序中,我有一个带有以下onClick事件的按钮

In both my Windows and Android apps, I have a button with the following onClick event

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对话框(不同的形式,取决于平台)

In the execute routine below, a ShowModal dialog is displayed to the user ( a different form depending on platform)

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上,我之前得到了结果我得到模式对话框。不知道为什么吗?

This works great for windows, but on Android, I get my result (i.e., the showmessage) before I get the modal dialog box. Not sure why?

推荐答案

删除您的 IFDEF 语句并查看您实际上在做什么:

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;

从功能上来说还可以(尽管它没有分配 Result 基于对话框的 ModalResult )。

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;

这不符合Embarcadero文档中概述的规则:

This is not following the rules outlined in Embarcadero's documentation:

FireMonkey移动应用程序中的ShowModal对话框

更糟糕的是, ShowModal()的重载版本需要一个匿名过程,因此您的 Execute()将在模式窗体关闭之前退出。它不能等待表单退出。因此,您将不得不重新设计代码来处理该问题。

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.

尝试更多类似的方法:

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;

或者,您可以摆脱 try / finally 界面

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;

这篇关于delphi XE-5跨平台开发-调用显示模式表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆