Site icon Embarcadero RAD Studio, Delphi, & C++Builder Blogs

How to Use FMX Dialogs Correctly in Delphi Apps

How to Use FMX Dialogs Correctly in Delphi Apps

Do you want to use FMX dialogs in Delphi applications? Read all about how to do this in this article from Tech Partner Softacom.

How to Use FMX Dialogs Correctly in Delphi Apps

Delphi FMX provides support for customized native dialog boxes (like those used for confirmations and warnings), which are available on all supported target platforms. This article will show the basics and the rules of using these dialogs correctly in your Delphi FMX apps.

What Dialogs Are Available?

There are 3 kinds of native dialogs available in FMX for every OS – Windows, Linux, macOS, iOS, and Android:

Basics of FMX Dialogs

Dialog behavior

According to the platform, dialogs can have two different behaviors:

The methods for calling Sync dialogs are functions that return responses to the executing app, while the methods for calling Async dialogs are procedures containing anonymous methods (with the dialog responses as parameters) that are executed when the dialog is closed.

Both behaviors are implemented in FMX platform services.

The actual FMX architecture provides two concepts for using these dialogs, you can choose between:

Dialog type

For the “MessageDialog” kind, you have to define the type of your dialog box, which will affect its appearance. Mostly the title of the dialog box (which is localized to the underlying OS language).

The type of the dialog box is set by a value of “TMsgDlgType”:

TMsgDlgType = (mtWarning, mtError, mtInformation, mtConfirmation, mtCustom);
ValueMeaningDialog box title
mtWarningWarns the user about a potential issue.Warning
mtErrorInforms the user of an error that occurred.Error
mtInformationProvides information to the user.Information
mtConfirmationAsks the user for confirmation.Confirm
mtCustomNone of the above.Your project name

The possible values of “TMsgDlgType”

Dialog box buttons

For the “MessageDialog,” you can choose a set of buttons (their type is “TMsgDlgBtn”) to appear at the MessageDialog bottom. Also, the captions on these buttons are localized according to the OS language.

Each of these buttons, when clicked, will close the dialog box and return a corresponding integer value as “TModalResult”. Because, in fact, the dialog box is a modal form, and setting the value of its TModalResult property to a no-zero integer value will close the modal form.

The returned TModalResult value can be used in the caller app, either assigned directly to a variable (in case of Sync dialogs) or in an anonymous method to perform custom actions after closing the dialog box (in case of Async dialogs).

The table below enumerates the MessageDialog buttons and their corresponding returned ModalResult (as named constants and integers):

TMsgDlgBtn valueCorresponding returned valueModalResult corresponding integer value
mbOKmrOk1
mbCancelmrCancel2
mbAbortmrAbort3
mbRetrymrRetry4
mbIgnoremrIgnore5
mbYesmrYes6
mbNomrNo7
mbClosemrClose8
mbHelpmrHelp9
mbAllmrAll12
mbNoToAllmrNoToAll13
mbYesToAllmrYesToAll14

Also, the “FMX.Dialogs” unit defines constants that you can use to represent some predefined sets of buttons, as shown in the following table:

mbYesNoTMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo
mbYesNoCancelTMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo, TMsgDlgBtn.mbCancel
mbYesAllNoAllCancelTMsgDlgBtn.mbYes, TMsgDlgBtn.mbYesToAll, TMsgDlgBtn.mbNo, TMsgDlgBtn.mbNoToAll, TMsgDlgBtn.mbCancel
mbOKCancelTMsgDlgBtn.mbOK, TMsgDlgBtn.mbCancel
mbAbortRetryIgnoreTMsgDlgBtn.mbAbort, TMsgDlgBtn.mbRetry, TMsgDlgBtn.mbIgnore
mbAbortIgnoreTMsgDlgBtn.mbAbort, TMsgDlgBtn.mbIgnore

How to use the different FireMonkey FMX dialogs?

Now, let’s see how to use each kind of these native dialogs.

What is the difference between the Sync and Async versions of message dialogs in FireMonkey FMX?

There are two versions – “sync” and “async”. The sync version is more like the kind of message dialog that you may have used with VCL apps on Windows. You can read the full details in the Embarcadero DocWiki entry here: https://docwiki.embarcadero.com/Libraries/en/FMX.DialogService.TDialogService.ShowMessage

Briefly, from that page here is an explanation of the differences between Sync and Async:

How to use the FireMonkey FMX “ShowMessage” version of a dialog

In the simplest kind of dialog, you only need to specify the text that will be shown. The code for calling ShowMessage Async:

procedure TForm1.Button1Click(Sender: TObject);
var
  AsyncService: IFMXDialogServiceAsync;
begin
  if TPlatformServices.Current.SupportsPlatformService (IFMXDialogServiceAsync, IInterface(AsyncService)) then
  begin
    AsyncService.ShowMessageAsync(‘This is ShowMessage Async’);
  end;
end;

The code for calling ShowMessage Sync:

procedure TForm1.Button1Click(Sender: TObject);
var
  SyncService: IFMXDialogServiceSync;
begin
  if TPlatformServices.Current.SupportsPlatformService(IFMXDialogServiceSync, IInterface(SyncService)) then
  begin
    SyncService.ShowMessageSync(‘This is ShowMessage Sync’);
  end;
end;

How to use the FireMonkey FMX “MessageDialog” version of a dialog

As explained above, to use MessageDialog you need to specify:

For Async MessageDialog, you need, as an additional parameter, an anonymous method to handle the dialog result like the following code snippet:

procedure(const AResult: TModalResult)
begin
  case AResult of
    mrYES:
      Label1.Text := 'YES';
  end;
end

But for Sync MessageDialog, the dialog result is returned as an integer from the dialog calling method.

This is how to call MessageDialog Async:

procedure TForm1.Button1Click(Sender: TObject);
var
  AsyncService: IFMXDialogServiceAsync;
begin
  if TPlatformServices.Current.SupportsPlatformService(IFMXDialogServiceAsync, IInterface(AsyncService)) then
  begin
    AsyncService.MessageDialogAsync('Question ?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], TMsgDlgBtn.mbNo, 0, 
     procedure(const AResult: TModalResult)
     begin
       case AResult of
         mrYES:
           Label1.Text := 'YES';
       end;
     end);
  end;
end;

Here’s the code for calling MessageDialog Sync:

procedure TForm1.Button1Click(Sender: TObject);
var
  SyncService: IFMXDialogServiceSync;
  rValue: integer;
begin
  if TPlatformServices.Current.SupportsPlatformService(IFMXDialogServiceSync, IInterface(SyncService)) then
  begin
    rValue := SyncService.MessageDialogSync('Question ?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], TMsgDlgBtn.mbNo, 0);
    Label1.Text := rValue.ToString;
  end;
end;

How to use the FireMonkey FMX “InputQuery” version of a dialog

To use InputQuery, you need to specify:

For Async InputQuery, you need, as an additional parameter, an anonymous method to handle dialog result (clicked button) and the user input values, like the following code snippet:

procedure (const AResult: TModalResult; const AValues: array of string)
begin
  case AResult of
    mrOk:
      Label1.Text := AValues[0] + '/' + AValues[1];
  end;
end

But for Sync InputQuery, the dialog calling function returns a boolean value (true if the user clicks the OK button). Then the user input values can be accessed through the Values variable.

The code for calling InputQuery Async:

procedure TForm1.Button1Click(Sender: TObject);
var
  AsyncService: IFMXDialogServiceAsync;
  caption, inData: array[0..1] of string;
begin
  caption[0] := 'Name :';
  caption[1] := #1 + 'Pass :'; // Masking function when #1 attached in front
  // Setting initial values
  inData[0] := 'admin';
  inData[1] := '1234';
  if TPlatformServices.Current.SupportsPlatformService(IFMXDialogServiceAsync, IInterface(AsyncService)) then
  begin
    AsyncService.InputQueryAsync('Input login credentials', caption, inData,
      procedure (const AResult: TModalResult; const AValues: array of string)
      begin
        case AResult of
          mrOk:
            Label1.Text := AValues[0] + '/' + AValues[1];
        end;
      end);
  end;
end;

The code for calling InputQuery Sync:

procedure TForm1.Button1Click(Sender: TObject);
var
  SyncService: IFMXDialogServiceSync;
  caption, inData: array[0..1] of string;
begin
  caption[0] := 'Name :';
  caption[1] := #1 + 'Pass :'; // Masking function when #1 attached in front
  // Setting initial values
  inData[0] := 'admin';
  inData[1] := '1234';
  if TPlatformServices.Current.SupportsPlatformService(IFMXDialogServiceSync, IInterface(SyncService)) then
  begin
    if SyncService.InputQuerySync('Input login credentials', caption, inData) 
    then
      Label1.Text := inData[0] + '/' + inData[1];
  end;
end;

That’s it! Are you ready to use the power of FireMonkey FMX dialogs in your apps?

Like any other component in the Delphi frameworks, knowing the mechanism and the basics behind native dialogs allows the developer to use them correctly and effectively in their projects.


If you want to try out projects of your own and you don’t have a copy of the latest version of RAD Studio with Delphi, you can go to the products page and download a free fully working trial version.

 

Exit mobile version