12
votes

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:

enter image description here

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;
3
You can set local variables from within anonymous methods, so that bit is OK. I can't see anything wrong with the rest either.Dsm

3 Answers

9
votes

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.

3
votes

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!

0
votes

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.