Reputation: 929
I have a VCL application that I am porting to FireMonkey. One of the things that I ran into is that MessageDlg(...)
is deprecated in FireMonkey. On digging a bit further, I understand that I have to use the FMX.DialogService.MessageDialog
method. So I created a function to display a dialog:
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;
I don't think that I am doing this right as I am not sure I can set a local variable inside an anonymous method, but it compiles nevertheless.
I call it like so:
if GetDeleteConfirmation('Are you sure you want to delete this entry?')<>'Y' then
exit;
When I run it, the message dialog shown is this:
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.
I am using Delphi 10.1 Berlin Update 2.
Many thanks in advance!
EDIT 20170320: I corrected my code on the basis of the correct answer by @LURD below and am including it here for completeness:
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;
Upvotes: 18
Views: 25041
Reputation: 2930
Based on other answers, I've added a "Confirm" class function (adapted to return a Boolean) to TApplicationHelper (which also has some extra methods, removed here), currently maintained under the READCOM_App repository
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 https://stackoverflow.com/questions/42852945/delphi-correctly-displaying-a-message-dialog-in-firemonkey-and-returning-the-m
class procedure TApplicationHelper.Confirm(const Prompt: String; const SetConfirmationResult: TProc<Boolean>); //based on https://stackoverflow.com/questions/42852945/delphi-correctly-displaying-a-message-dialog-in-firemonkey-and-returning-the-m
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.
usage example is in the MainForm of READCOM_App
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
);
end;
where MSG_CONFIRM_CLEAR_STORY is declared as
resourcestring
MSG_CONFIRM_CLEAR_STORY = 'Clearing story: are you sure?';
Upvotes: 1
Reputation: 1
This method works nicely in Alexandria 11.0 application deployed in Android SDK 29.
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;
Upvotes: 0
Reputation: 1
This is my answer, perfect function whith Firemonkey delphi Rio 10.3.
The code is inside component button.
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;
Upvotes: 0
Reputation: 60
On mobile OS's like android there's no such thing as modal dialog.
VCL version is like this: case MessageDlg(.....) of mrOk : DoOkStuff; mrCancel : DoCancelStuff end;
FMX version must be like this: TDialogService.MessageDialog(....., procedure (const AResult: TModalResult) begin case AResult of mrOk : DoOkStuff; mrCancel : DoCancelStuff end; end);
Everything that must be done after closing, should be in this anonymous proc.
Do not try to mimic VCL's MessageDialog and do not use Application.ProcessMessages.
Upvotes: 1
Reputation: 34899
Question:
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.
The Fmx.TDialogService.MessageDialog
does not support arbitrary combinations of dialog buttons.
Looking into the source code (Fmx.Dialogs.Win.pas) reveals these valid combinations (mbHelp
can be included in all combinations):
- mbOk
- mbOk,mbCancel
- mbYes,mbNo,mbCancel
- mbYes, mbYesToAll, mbNo, mbNoToAll, mbCancel
- mbAbort, mbRetry, mbIgnore
- mbAbort, mbIgnore
- mbYes, mbNo
- mbAbort, mbCancel
This means that [mbYes,mbCancel]
is not a valid combination, use [mbOk,mbCancel]
instead for example.
A final note about the Fmx.TDialogService.MessageDialog
. It is normally a synchronous dialog on desktop applications, but asynchronous on mobile platforms. The use case will look a bit different depending on those conditions, so for a multi-platform application, check the value of TDialogService.PreferredMode.
Upvotes: 16
Reputation: 572
Hi friend try this code:
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;
Or this:
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;
Enjoy it!
Upvotes: 3