delphi XE-5跨平台开发-调用showmodal表单
我目前正在使用Delphi XE-5在Windows桌面上开发跨平台应用程序。我有一个用于跨平台开发的单元(在本例中,让我们只使用Windows和Android) 在我的Windows和Android应用程序中,我都有一个带有以下onClick事件的按钮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
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;