VCL had a nice and uniform message box system. Most important (and convenient), the messages were blocking. Because of the Android platform which does not support asynchronous messages, all this is gone. So I document here the behavior of few different ways in which we can display message boxes in FMX. None is perfect (not even by far). I guess I will end up writing my own library.
You will find the full source code and the documentation (conclusions) here: https://github.com/GabrielOnDelphi/Delphi-LightSaber/tree/main/Demo/FMX%20-%20Demo%20Message%20boxes
// Synchronicity: Uses TDialogServiceAsync on Android, and TDialogServiceSync on the other platforms
// Custom caption: No
// Deprecated: No
// Icons: No
// Ding: No
// Has X button: Yes
procedure TForm1.btnFmxDialogsClick(Sender: TObject);
begin
Caption:= ”;
FMX.Dialogs.ShowMessage(‘FMX.Dialogs.ShowMessage’);
Caption:= ‘Sync’;
end;
{
MessageDlg
Warning: FMX.Dialogs.MessageDlg is deprecated. (https://docwiki.embarcadero.com/Libraries/Berlin/en/FMX.Dialogs.MessageDlg) }
procedure TForm1.btnFmxDialogs2Click(Sender: TObject);
begin
Caption:= ”;
FMX.Dialogs.MessageDlg(‘FMX.Dialogs.MessageDlg’, TMsgDlgType.mtInformation, [TMsgDlgBtn.mbOK, TMsgDlgBtn.mbCancel], 0);
Caption:= ‘sssss’;
end;
// Synchronicity: Sync
// Custom caption: No
// Icons: Yes
// Ding: Yes
// Has X button: Yes
// You can force TDialogService.PreferredMode := TPreferredMode.Sync on mobile to simulate synchronous behavior, but not recommended
procedure TForm1.Button3Click(Sender: TObject);
begin
Caption:= ”;
TDialogService.MessageDialog(‘TDialogService.MessageDialog’,
TMsgDlgType.mtInformation,
[TMsgDlgBtn.mbOK, TMsgDlgBtn.mbCancel],
TMsgDlgBtn.mbOK, 0, NIL);
Caption:= ‘Sync’;
end;
// Has X button: Yes BUT it is disabled (so it does nothing)
procedure TForm1.btnQuestionClick(Sender: TObject);
begin
Caption:= ”;
TDialogService.MessageDialog(‘TDialogService.MessageDialog question’,
TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo],
TMsgDlgBtn.mbYes, 0,
procedure(const AResult: TModalResult)
begin
if AResult = mrYes
then DoSomething
else Caption:= ‘Canceled’;
end
);
Caption:= ‘Sync’;
end;
// Synchronicity: Async
// Based on TDialogServiceAsync.MessageDialog
// Custom caption: No
// Icons: No
// Ding: Yes
// Has X button: No
procedure TForm1.btnMessageInfoClick(Sender: TObject);
begin
Caption:= ”;
MessageInfo(‘MessageInfo’, ‘No caption?’);
Caption:= ‘Async’;
//MessageWarning(‘Hello info’, ‘Caption’);
//MessageError(‘Hello info’, ‘Caption’);
//MessageErrorSubmit(‘Hello info’, ‘Caption’);
end;
// TDialogService.InputQuery() is a method in the FireMonkey (FMX) framework that provides a cross-platform way to prompt the user for input.
// InputQuery can work synchronously or asynchronously depending on the preferred mode.
// InputQuery internally calls TDialogServiceAsync.InputQuery or TDialogServiceSync.InputQuery.
// Has X button: Yes BUT it does nothing!
procedure TForm1.btnInputQuery1Click(Sender: TObject);
begin
FMX.DialogService.TDialogService.PreferredMode:= TDialogService.TPreferredMode.Async;
TDialogService.InputQuery(
‘Enter Your Name’, // Dialog title
[‘Name:’], // Array of prompts for input fields
[”], // Array of default values
procedure(const AResult: TModalResult; const AValues: array of string)
begin
if AResult = mrOk
then Caption:= ‘Hello, ‘ + AValues[0]
else Caption:= ‘User cancelled’;
end
);
end;
// InputQuery supports multiple input fields. For instance, to collect a first and last name:
procedure TForm1.btnInputQuery2Click(Sender: TObject);
begin
FMX.DialogService.TDialogService.PreferredMode:= TDialogService.TPreferredMode.Async;
TDialogService.InputQuery(
‘Enter Your Details’,
[‘First Name:’, ‘Last Name:’],
[”, ”],
procedure(const AResult: TModalResult; const AValues: array of string)
begin
if AResult = mrOk
then Caption := ‘Hello, ‘ + AValues[0] + ‘ ‘ + AValues[1];
end
);
end;
// Wrong usage example.
// Because of the asynchronicity, the Caption will be initially set to ‘John Doe’. Only after the user enters its name, the Caption will show correct data!
procedure TForm1.btnInputQuery3Click(Sender: TObject);
VAR UserName: string; // Scope Capture: The anonymous callback can capture variables from the surrounding scope, which is useful for maintaining context:
begin
FMX.DialogService.TDialogService.PreferredMode:= TDialogService.TPreferredMode.Async;
UserName:= ‘John Doe’;
TDialogService.InputQuery(
‘Enter Your Details’,
[‘First Name:’, ‘Last Name:’],
[”, ”],
procedure(const AResult: TModalResult; const AValues: array of string)
begin
if AResult = mrOk
then Caption := ‘Hello, ‘ + AValues[0] + ‘ ‘ + AValues[1];
UserName:= AValues[0];
end
);
Caption:= UserName; // This is executed BEFORE the user has a chance to enter its name!
end;