Archive
HowTo: show a confirmation dialog with Delphi FireMonkey UI library
Here’s my answer at https://stackoverflow.com/a/71728787/903783 on how to show a confirmation dialog with Delphi’s cross-platform FireMonkey UI library.
Based on other answers, I’ve added a “Confirm” class function (adapted to return a Boolean) to TApplicationHelper (which also has an untested function to get the executable filename), currently maintained under the READCOM_App repository.
Update: had to modify the answer to use a callback so that it also works on platforms where FMX supports only asynchronous dialogs, like Android
unit Zoomicon.Helpers.FMX.Forms.ApplicationHelper;
interface
uses
FMX.Forms; //for TApplication
type
TApplicationHelper = class helper for TApplication
public
function ExeName: String;
class function Confirm(Prompt: String): Boolean;
end;
implementation
uses
{$IFDEF ANDROID}
System.SysUtils, //TODO: is this needed?
Androidapi.Helpers, //for TAndroidHelper, JStringToString
Androidapi.Jni.JavaTypes, //to avoid "H2443 Inline function 'JStringToString' has not been expanded"
{$ENDIF}
System.UITypes, //for TMsgDlgType
FMX.DialogService, //for TDialogService
FMX.Dialogs; //for mbYesNo
{$region 'TApplicationHelper'}
//from https://gist.github.com/freeonterminate/2f7b2e29e40fa30ed3c4
function TApplicationHelper.ExeName: String;
begin
Result := ParamStr(0);
{$IFDEF ANDROID}
if (Result.IsEmpty) then
Result := JStringToString(TAndroidHelper.Context.getPackageCodePath);
{$ENDIF}
end;
//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>);
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?';
HowTo: show inner exception message if available, else outer one
Sometimes when you catch an exception in .NET, the message it prints out isn’t very informative, since it is wrapping another exception that had been thrown a bit inner in the code. That exception is in that case accessible via InnerException of the Exception instance.
That inner exception is also an Exception, so one would like to use its Message instead of the outer exception’s one, if an inner exception exists and, only if an inner exception doesn’t exist use the caught exception’s message. Here’s a clean-looking pattern I’ve coined up to achieve this while working on the TrackingCam application:
try
{
//…
}
catch (Exception e)
{
MessageBox.Show((e.InnerException ?? e).Message);
}
the ?? operator returns e.InnerException if it is not null, else falls back to returning e. Those two results are both of type Exception, so you can use Message on them, by putting the ?? operator’s expression in parentheses.