I am porting an older project (app for iOS ans Android) for a customer from an older AppMethod version to the newest RAD Studio version (10.0 Berlin). MessageDlg
and similar were used often in the project but this does not work anymore. The apps shows a message, that modal dialogs are not supported on Android. I know and understand why this is so for the Android platform (so please don't mark this question as a dublicate by referencing to an explanation - I'm asking for something else!).
Firemonkey allows to set an anonymous function to be executed asynchronously after the user taps on a button in the dialog box or when it is closed. However, there is often code which depends on users decision or code which must be executed after the dialog box, regardless of which button the user taps on. For example, a dialog box must ask the user for his decision in the middle of an ongoing operation. Further operations then depend on the users decision (which might also include to stop further code execution in the current application!). Since RAD Studio does not support blocking dialogs on Android, I seem to be forced to break up my code - from one function to multiple functions (worse readability...). This gets even more complicated when there are nested function calls with possible modal dialog boxes, which require user interaction.
Is there still a way to emulate blocking dialogs somehow? It doesn't has to be perfect. I just don't want to rewrite a lot of code and outsource even small code fragments into many separate functions, everwhere where user interaction is required.
OK, I think the following "dirty" solution might be sufficient for me:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.DialogService,
FMX.Controls.Presentation, FMX.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
blockDlg: array[0..99] of Boolean;
blockDlgIdx: Integer = 0;
implementation
{$R *.fmx}
procedure NShowMessageAsync(AMessage: String);
begin
TDialogService.ShowMessage(AMessage);
end;
procedure NShowMessageSync(AMessage: String);
var
locBlockIdx: Integer;
begin
if blockDlgIdx = Length(blockDlg)-1 then blockDlgIdx := 0 else Inc(blockDlgIdx);
locBlockIdx := blockDlgIdx;
blockDlg[locBlockIdx] := true;
TDialogService.ShowMessage(AMessage,
procedure(const AResult: TModalResult)
begin
blockDlg[locBlockIdx] := false;
end);
while blockDlg[locBlockIdx] do begin
Sleep(40);
Application.ProcessMessages();
end;
end;
procedure NMessageDialogAsync(const AMessage: string; const ADialogType: TMsgDlgType;
const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn;
const AHelpCtx: LongInt);
begin
TDialogService.MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton,
AHelpCtx, procedure(const AResult: TModalResult) begin end);
end;
function NMessageDialogSync(const AMessage: string; const ADialogType: TMsgDlgType;
const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn;
const AHelpCtx: LongInt): TModalResult;
var
locBlockIdx: Integer;
LModalResult: TModalResult;
begin
Result := -1;
if blockDlgIdx = Length(blockDlg)-1 then blockDlgIdx := 0 else Inc(blockDlgIdx);
locBlockIdx := blockDlgIdx;
blockDlg[locBlockIdx] := true;
TDialogService.MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton, AHelpCtx,
procedure(const AResult: TModalResult)
begin
LModalResult := AResult;
blockDlg[locBlockIdx] := false;
end);
while blockDlg[locBlockIdx] do begin
Sleep(40);
Application.ProcessMessages();
end;
Result := LModalResult;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
mr: TModalResult;
begin
mr := NMessageDialogSync('1',
System.UITypes.TMsgDlgType.mtInformation,
[System.UITypes.TMsgDlgBtn.mbYes, System.UITypes.TMsgDlgBtn.mbNo, System.UITypes.TMsgDlgBtn.mbCancel],
System.UITypes.TMsgDlgBtn.mbYes,
0);
NShowMessageSync(IntToStr(mr));
mr := NMessageDialogSync('2',
System.UITypes.TMsgDlgType.mtWarning,
[System.UITypes.TMsgDlgBtn.mbYesToAll, System.UITypes.TMsgDlgBtn.mbAbort],
System.UITypes.TMsgDlgBtn.mbAbort,
0);
NShowMessageSync(IntToStr(mr));
mr := NMessageDialogSync('3',
System.UITypes.TMsgDlgType.mtInformation,
[System.UITypes.TMsgDlgBtn.mbIgnore, System.UITypes.TMsgDlgBtn.mbAll, System.UITypes.TMsgDlgBtn.mbHelp, System.UITypes.TMsgDlgBtn.mbClose],
System.UITypes.TMsgDlgBtn.mbClose,
0);
NShowMessageSync(IntToStr(mr));
Form1.Fill.Kind := TBrushKind.Solid;
if Form1.Fill.Color = TAlphaColors.Red then
Form1.Fill.Color := TAlphaColors.Blue
else
Form1.Fill.Color := TAlphaColors.Red;
end;
end.
Not very clean, but at least I can use this for a while.