Delphi - 在 FireMonkey 中正确显示消息对话框并返回模态结果
Delphi - Correctly displaying a Message Dialog in FireMonkey and returning the Modal Result
我有一个要移植到 FireMonkey 的 VCL 应用程序。我 运行 感兴趣的一件事是 MessageDlg(...)
在 FireMonkey 中被弃用。进一步挖掘,我明白我必须使用 FMX.DialogService.MessageDialog
方法。所以我创建了一个显示对话框的函数:
function TfMain.GetDeleteConfirmation(AMessage: String): String;
var
lResult: String;
begin
lResult:='';
TDialogService.PreferredMode:=TDialogService.TPreferredMode.Platform;
TDialogService.MessageDialog(AMessage, TMsgDlgType.mtConfirmation,
[ TMsgDlgBtn.mbYes, TMsgDlgBtn.mbCancel ], TMsgDlgBtn.mbCancel, 0,
procedure(const AResult: TModalResult)
begin
case AResult of
mrYes: lResult:='Y';
mrCancel: lResult:='C';
end;
end);
Result:=lResult;
end;
我不认为我这样做是正确的,因为我不确定我是否可以在匿名方法中设置局部变量,但它仍然可以编译。
我是这样称呼它的:
if GetDeleteConfirmation('Are you sure you want to delete this entry?')<>'Y' then
exit;
当我运行它时,显示的消息对话框是这样的:
它不显示 2 个按钮(是,取消)。有人可以帮我解决这个问题 - 即正确显示带有 2 个按钮的消息对话框,并将消息对话框的模态结果作为函数的结果发回。
我正在使用 Delphi 10.1 柏林更新 2。
非常感谢!
编辑 20170320: 我根据下面@LURD 的正确答案更正了我的代码,为了完整起见,我将其包含在此处:
function TfMain.GetDeleteConfirmation(AMessage: String): String;
var
lResultStr: String;
begin
lResultStr:='';
TDialogService.PreferredMode:=TDialogService.TPreferredMode.Platform;
TDialogService.MessageDialog(AMessage, TMsgDlgType.mtConfirmation,
FMX.Dialogs.mbYesNo, TMsgDlgBtn.mbNo, 0,
procedure(const AResult: TModalResult)
begin
case AResult of
mrYes: lResultStr:='Y';
mrNo: lResultStr:='N';
end;
end);
Result:=lResultStr;
end;
嗨朋友试试这个代码:
function myMessageDialog(const AMessage: string; const ADialogType: TMsgDlgType;
const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn): Integer;
var
mr: TModalResult;
begin
mr:=mrNone;
// standart call with callback anonimous method
TDialogService.MessageDialog(AMessage, ADialogType, AButtons,
ADefaultButton, 0,
procedure (const AResult: TModalResult)
begin
mr:=AResult
end);
while mr = mrNone do // wait for modal result
Application.ProcessMessages;
Result:=mr;
end;
或者这样:
function MsgBox(const AMessage: string; const ADialogType: TMsgDlgType; const AButtons: TMsgDlgButtons;
const ADefaultButton: TMsgDlgBtn ): Integer;
var
myAns: Integer;
IsDisplayed: Boolean;
begin
myAns := -1;
IsDisplayed := False;
While myAns = -1 do
Begin
if IsDisplayed = False then
TDialogService.MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton, 0,
procedure (const AResult: TModalResult)
begin
myAns := AResult;
IsDisplayed := True;
end);
IsDisplayed := True;
Application.ProcessMessages;
End;
Result := myAns;
end;
尽情享受吧!
问题:
It does not show the 2 buttons (Yes, Cancel). Could someone please help me get this right - i.e. correctly show the message dialog with the 2 buttons and send the modal result of the message dialog back as the Result of the function.
Fmx.TDialogService.MessageDialog
不支持对话框按钮的任意组合。
查看源代码 (Fmx.Dialogs.Win.pas) 揭示了这些有效组合(mbHelp
可以包含在所有组合中):
- mbOk
- mbOk,mbCancel
- mbYes,mbNo,mbCancel
- mbYes, mbYesToAll, mbNo,
mbNoToAll, mbCancel
- mbAbort, mbRetry, mbIgnore
- mbAbort, mbIgnore
- mbYes, mbNo
- mbAbort, mbCancel
这意味着 [mbYes,mbCancel]
不是一个有效的组合,例如使用 [mbOk,mbCancel]
代替。
关于 Fmx.TDialogService.MessageDialog
的最后说明。它通常是桌面应用程序上的同步对话框,但在移动平台上是异步的。根据这些条件,用例看起来会有些不同,因此对于多平台应用程序,请检查 TDialogService.PreferredMode 的值。
在移动设备上 OS 就像 android 没有模态对话框这样的东西。
VCL版本是这样的:
case MessageDlg(.....) 的
mrOk : DoOkStuff;
取消先生:DoCancelStuff
结束;
FMX 版本必须是这样的:
TDialogService.MessageDialog(.......,
程序(常量 AResult:TModalResult)
开始
案例A的结果
mrOk : DoOkStuff;
取消先生:DoCancelStuff
结尾;
结束);
关闭后必须完成的所有事情都应该在这个匿名过程中。
不要试图模仿 VCL 的 MessageDialog 并且不要使用 Application.ProcessMessages。
这是我的答案,Firemonkey delphi Rio 10.3 的完美功能。
代码在组件按钮内。
procedure TForm3.Button4Click(Sender: TObject);
begin
MessageDlg('seleccione un boton',System.UITypes.TMsgDlgType.mtConfirmation,
[System.UITypes.TMsgDlgBtn.mbYes,
System.UITypes.TMsgDlgBtn.mbNo],0,prozedurale (const AResult: System.UITypes.TModalResult)
begin
if AResult=mrYES Then
ShowMessage('tu seleccioneste YES')
else
ShowMessage('tu seleccioneste No');
end); //Fin de MesageDlg
end;
此方法在 Android SDK 29 中部署的 Alexandria 11.0 应用程序中运行良好。
procedure TForm1.Button1Click(Sender: TObject);
begin
TDialogService.MessageDialog('Select a button:',
TMsgDlgType.mtConfirmation,
FMX.Dialogs.mbYesNoCancel,
TMsgDlgBtn.mbNo,
0,
procedure(const AResult: System.UITypes.TModalResult)
begin
if AResult = mrYES Then
ShowMessage('Yes was selected')
else if AResult = mrNo Then
ShowMessage('No was selected')
else if AResult = mrCancel Then
ShowMessage('Cancel was selected');
end);
end;
根据其他答案,我在 TApplicationHelper (which also has some extra methods, removed here), currently maintained under the READCOM_App 存储库
中添加了一个“确认”class 函数(适用于 return 布尔值)
unit Zoomicon.Helpers.FMX.Forms.ApplicationHelper;
interface
uses
FMX.Forms; //for TApplication
type
TApplicationHelper = class helper for TApplication
public
class function Confirm(Prompt: String): Boolean;
end;
implementation
uses
System.UITypes, //for TMsgDlgType
FMX.DialogService, //for TDialogService
FMX.Dialogs; //for mbYesNo
{$region 'TApplicationHelper'}
//based on
class procedure TApplicationHelper.Confirm(const Prompt: String; const SetConfirmationResult: TProc<Boolean>); //based on
begin
with TDialogService do
begin
PreferredMode := TPreferredMode.Platform;
MessageDialog(Prompt, TMsgDlgType.mtConfirmation, mbYesNo, TMsgDlgBtn.mbNo, 0,
procedure(const AResult: TModalResult)
begin
//Note: assuming this is executed on the main/UI thread later on, so we just call the "SetResult" callback procedure passing it the dialog result value
case AResult of
mrYes: SetConfirmationResult(true);
mrNo: SetConfirmationResult(false);
end;
end
);
end;
end;
{$endregion}
end.
用法示例在READCOM_App
的MainForm
procedure TMainForm.HUDactionNewExecute(Sender: TObject);
begin
TApplication.Confirm(MSG_CONFIRM_CLEAR_STORY, //confirmation done only at the action level //Note: could also use Application.Confirm since Confirm is defined as a class function in ApplicationHelper (and those can be called on object instances of the respective class too)
procedure(Confirmed: Boolean)
begin
if Confirmed and (not LoadDefaultDocument) then
NewRootStoryItem;
end
);
结束;
其中 MSG_CONFIRM_CLEAR_STORY 声明为
resourcestring
MSG_CONFIRM_CLEAR_STORY = 'Clearing story: are you sure?';
我有一个要移植到 FireMonkey 的 VCL 应用程序。我 运行 感兴趣的一件事是 MessageDlg(...)
在 FireMonkey 中被弃用。进一步挖掘,我明白我必须使用 FMX.DialogService.MessageDialog
方法。所以我创建了一个显示对话框的函数:
function TfMain.GetDeleteConfirmation(AMessage: String): String;
var
lResult: String;
begin
lResult:='';
TDialogService.PreferredMode:=TDialogService.TPreferredMode.Platform;
TDialogService.MessageDialog(AMessage, TMsgDlgType.mtConfirmation,
[ TMsgDlgBtn.mbYes, TMsgDlgBtn.mbCancel ], TMsgDlgBtn.mbCancel, 0,
procedure(const AResult: TModalResult)
begin
case AResult of
mrYes: lResult:='Y';
mrCancel: lResult:='C';
end;
end);
Result:=lResult;
end;
我不认为我这样做是正确的,因为我不确定我是否可以在匿名方法中设置局部变量,但它仍然可以编译。
我是这样称呼它的:
if GetDeleteConfirmation('Are you sure you want to delete this entry?')<>'Y' then
exit;
当我运行它时,显示的消息对话框是这样的:
它不显示 2 个按钮(是,取消)。有人可以帮我解决这个问题 - 即正确显示带有 2 个按钮的消息对话框,并将消息对话框的模态结果作为函数的结果发回。
我正在使用 Delphi 10.1 柏林更新 2。
非常感谢!
编辑 20170320: 我根据下面@LURD 的正确答案更正了我的代码,为了完整起见,我将其包含在此处:
function TfMain.GetDeleteConfirmation(AMessage: String): String;
var
lResultStr: String;
begin
lResultStr:='';
TDialogService.PreferredMode:=TDialogService.TPreferredMode.Platform;
TDialogService.MessageDialog(AMessage, TMsgDlgType.mtConfirmation,
FMX.Dialogs.mbYesNo, TMsgDlgBtn.mbNo, 0,
procedure(const AResult: TModalResult)
begin
case AResult of
mrYes: lResultStr:='Y';
mrNo: lResultStr:='N';
end;
end);
Result:=lResultStr;
end;
嗨朋友试试这个代码:
function myMessageDialog(const AMessage: string; const ADialogType: TMsgDlgType;
const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn): Integer;
var
mr: TModalResult;
begin
mr:=mrNone;
// standart call with callback anonimous method
TDialogService.MessageDialog(AMessage, ADialogType, AButtons,
ADefaultButton, 0,
procedure (const AResult: TModalResult)
begin
mr:=AResult
end);
while mr = mrNone do // wait for modal result
Application.ProcessMessages;
Result:=mr;
end;
或者这样:
function MsgBox(const AMessage: string; const ADialogType: TMsgDlgType; const AButtons: TMsgDlgButtons;
const ADefaultButton: TMsgDlgBtn ): Integer;
var
myAns: Integer;
IsDisplayed: Boolean;
begin
myAns := -1;
IsDisplayed := False;
While myAns = -1 do
Begin
if IsDisplayed = False then
TDialogService.MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton, 0,
procedure (const AResult: TModalResult)
begin
myAns := AResult;
IsDisplayed := True;
end);
IsDisplayed := True;
Application.ProcessMessages;
End;
Result := myAns;
end;
尽情享受吧!
问题:
It does not show the 2 buttons (Yes, Cancel). Could someone please help me get this right - i.e. correctly show the message dialog with the 2 buttons and send the modal result of the message dialog back as the Result of the function.
Fmx.TDialogService.MessageDialog
不支持对话框按钮的任意组合。
查看源代码 (Fmx.Dialogs.Win.pas) 揭示了这些有效组合(mbHelp
可以包含在所有组合中):
- mbOk
- mbOk,mbCancel
- mbYes,mbNo,mbCancel
- mbYes, mbYesToAll, mbNo, mbNoToAll, mbCancel
- mbAbort, mbRetry, mbIgnore
- mbAbort, mbIgnore
- mbYes, mbNo
- mbAbort, mbCancel
这意味着 [mbYes,mbCancel]
不是一个有效的组合,例如使用 [mbOk,mbCancel]
代替。
关于 Fmx.TDialogService.MessageDialog
的最后说明。它通常是桌面应用程序上的同步对话框,但在移动平台上是异步的。根据这些条件,用例看起来会有些不同,因此对于多平台应用程序,请检查 TDialogService.PreferredMode 的值。
在移动设备上 OS 就像 android 没有模态对话框这样的东西。
VCL版本是这样的: case MessageDlg(.....) 的 mrOk : DoOkStuff; 取消先生:DoCancelStuff 结束;
FMX 版本必须是这样的: TDialogService.MessageDialog(......., 程序(常量 AResult:TModalResult) 开始 案例A的结果 mrOk : DoOkStuff; 取消先生:DoCancelStuff 结尾; 结束);
关闭后必须完成的所有事情都应该在这个匿名过程中。
不要试图模仿 VCL 的 MessageDialog 并且不要使用 Application.ProcessMessages。
这是我的答案,Firemonkey delphi Rio 10.3 的完美功能。
代码在组件按钮内。
procedure TForm3.Button4Click(Sender: TObject);
begin
MessageDlg('seleccione un boton',System.UITypes.TMsgDlgType.mtConfirmation,
[System.UITypes.TMsgDlgBtn.mbYes,
System.UITypes.TMsgDlgBtn.mbNo],0,prozedurale (const AResult: System.UITypes.TModalResult)
begin
if AResult=mrYES Then
ShowMessage('tu seleccioneste YES')
else
ShowMessage('tu seleccioneste No');
end); //Fin de MesageDlg
end;
此方法在 Android SDK 29 中部署的 Alexandria 11.0 应用程序中运行良好。
procedure TForm1.Button1Click(Sender: TObject);
begin
TDialogService.MessageDialog('Select a button:',
TMsgDlgType.mtConfirmation,
FMX.Dialogs.mbYesNoCancel,
TMsgDlgBtn.mbNo,
0,
procedure(const AResult: System.UITypes.TModalResult)
begin
if AResult = mrYES Then
ShowMessage('Yes was selected')
else if AResult = mrNo Then
ShowMessage('No was selected')
else if AResult = mrCancel Then
ShowMessage('Cancel was selected');
end);
end;
根据其他答案,我在 TApplicationHelper (which also has some extra methods, removed here), currently maintained under the READCOM_App 存储库
中添加了一个“确认”class 函数(适用于 return 布尔值)unit Zoomicon.Helpers.FMX.Forms.ApplicationHelper;
interface
uses
FMX.Forms; //for TApplication
type
TApplicationHelper = class helper for TApplication
public
class function Confirm(Prompt: String): Boolean;
end;
implementation
uses
System.UITypes, //for TMsgDlgType
FMX.DialogService, //for TDialogService
FMX.Dialogs; //for mbYesNo
{$region 'TApplicationHelper'}
//based on
class procedure TApplicationHelper.Confirm(const Prompt: String; const SetConfirmationResult: TProc<Boolean>); //based on
begin
with TDialogService do
begin
PreferredMode := TPreferredMode.Platform;
MessageDialog(Prompt, TMsgDlgType.mtConfirmation, mbYesNo, TMsgDlgBtn.mbNo, 0,
procedure(const AResult: TModalResult)
begin
//Note: assuming this is executed on the main/UI thread later on, so we just call the "SetResult" callback procedure passing it the dialog result value
case AResult of
mrYes: SetConfirmationResult(true);
mrNo: SetConfirmationResult(false);
end;
end
);
end;
end;
{$endregion}
end.
用法示例在READCOM_App
的MainFormprocedure TMainForm.HUDactionNewExecute(Sender: TObject);
begin
TApplication.Confirm(MSG_CONFIRM_CLEAR_STORY, //confirmation done only at the action level //Note: could also use Application.Confirm since Confirm is defined as a class function in ApplicationHelper (and those can be called on object instances of the respective class too)
procedure(Confirmed: Boolean)
begin
if Confirmed and (not LoadDefaultDocument) then
NewRootStoryItem;
end
);
结束;
其中 MSG_CONFIRM_CLEAR_STORY 声明为
resourcestring
MSG_CONFIRM_CLEAR_STORY = 'Clearing story: are you sure?';