0

I'm trying to do what my question says, when the user clicks the close button on the form, I want to prompt the user to confirm it, this is the code I came up with... It is problematic, when I click on the close button, it does prompt me to confirm, but the program closes anyway, irrelevant of the button I click, what am I doing wrong?

procedure TfrmLogin.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if MessageDlg('Are you sure you want to exit?', mtWarning, [tMsgDlgBtn.mbYes, tMsgDlgBtn.mbCancel], 0) = 0 then
    begin
      Application.Terminate;
    end;
end;
Michael
  • 91
  • 6

1 Answers1

2

When you read the documentation for TForm.OnClose, you must have missed the table telling you what you can put in the Action parameter:

The TCloseEvent type points to a method that handles the closing of a form. The value of the Action parameter determines if the form actually closes. These are the possible values of Action:

caNone

The form is not allowed to close, so nothing happens.

caHide

The form is not closed, but just hidden. Your application can still access a hidden form.

caFree

The form is closed and all allocated memory for the form is freed.

caMinimize

The form is minimized, rather than closed. This is the default action for MDI child forms.

Hence, you can do

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if MessageBox(Handle, 'Do you want to close this app?', 'Super App', MB_YESNOCANCEL) = ID_YES then
    Action := caHide
  else
    Action := caNone;
end;

But it is arguably better to use the OnCloseQuery event:

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := MessageBox(Handle, 'Do you want to close this app?', 'Super App', MB_YESNOCANCEL) = ID_YES;
end;
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • `caFree` would be more appropriate than `caHide` in this situation. But you are correct that `OnCloseQuery` would be a better choice than `OnClose`. – Remy Lebeau Sep 26 '21 at 19:58
  • @RemyLebeau: I don't agree. `caHide` is the default value. – Andreas Rejbrand Sep 26 '21 at 20:02
  • @AndreasRejbrand While `caHide` is the default value for any of the secondary forms it is not true for the main form. Otherwise you would not be able to close your application by closing the main form itself. – SilverWarior Sep 26 '21 at 20:21
  • @SilverWarior: It's `caHide` even for the main form. – Andreas Rejbrand Sep 26 '21 at 20:24
  • 3
    When the `MainForm` is closed, `Application.Terminate()` is called if `Action` is ANY value other than `caNone` (see the code in [this question](https://stackoverflow.com/q/49303888/65863)). So `caHide` vs `caFree` is moot for the `MainForm`, but `caFree` better conveys what is about to really happen during app shutdown (the Form will be destroyed, not hidden). – Remy Lebeau Sep 26 '21 at 20:34