delphi XE-5跨平台开发-调用显示模式表单 [英] delphi XE-5 cross platform development - calling a showmodal form
问题描述
我目前正在使用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 $ c在Windows上通过使用ARC
界面
:
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屋!