With the advent of the non-blocking MessageDlg in XE7, it seems that it's now impossible to conditionally prevent the app. from closing as we do in Windows (or did in XE5):
procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := False;
FCanClose := False;
FMX.Dialogs.MessageDlg('Exit?'
,
TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure(const AResult: TModalResult)
begin
if AResult = mrYes then
FCanClose := True;
end
);
CanClose := FCanClose;
end;
The MessageDlg (and the anonymous procedure) is called only AFTER the form has already closed, thereby defeating the object. Oh, and in case you're wondering why I'm using an FCanclose, it's because I got a compiler error about "not able to capture Canclose" in the anonymous procedure.
Now the other possibility I tried, was to put the MessageDlg in the FormKeyUp event handler and trap the vkHardwareBack.
procedure TfrmMain.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char;
Shift: TShiftState);
var
FService: IFMXVirtualKeyboardService;
begin
if Key = vkHardwareBack then
begin
TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyBoardService,
IInterface(FService));
if (FService <> nil) then
begin
if (TVirtualKeyBoardState.Visible in FService.VirtualKeyBoardState) then
else
begin
FMX.Dialogs.MessageDlg('Exit?'
,
TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure(const AResult: TModalResult)
begin
if AResult = mrYes then
Key := 0; // prevent exit, if Key could be "captured"
end
);
end;
end;
end;
But once again, the MessageDlg is only called AFTER the FormKeyUp eventhandler has finished executing, once again rendering the key setting useless! (if it could be "captured", that is)
How do I give the user the option to not close the app because maybe they hit the backbutton once too often, or perhaps because there is some task they need to complete before they can be allowed to exit?