MessageDlg - What if Closed Using the [X] Button in the Title Bar?

What is the ModalResult of a MessageDlg Function When [X] is Clicked?

Delphi's MessageDlg with
Delphi's MessageDlg with "X" result.

Delphi's MessageDlg function displays a message dialog box in the center of the screen.

If you already know about the MessageDlg function you can skip the first paragraph here.

But, before you do, answer the following question: MessageDlg is called and displays Yes and No buttons. User closes the dialog by clicking on the X button in the title bar. What is the result of the function?

Here's another question: how many users (in percentage) close a dialog form by simply clicking on the [x] button in the title?

I think too much. Either they do not understand what the dialog is asking or they are afraid to click any of the buttons.

Two overloaded versions of the MessageDlg function exist (in the "Dialogs" unit) to allow you to specify the type of the dialog, text of the message, a set of predefined buttons to appear on the dialog, and the default button, if needed.

Here's the signature of the MessageDlg:

 function MessageDlg(
   const Msg: string;
   DlgType: TMsgDlgType;
   Buttons: TMsgDlgButtons;
   HelpCtx: Longint;
   DefaultButton: TMsgDlgBtn): Integer; overload;
 
The DlgType parameter (TMsgDlgType type) indicates the purpose of the dialog and determines what image will be displayed in the dialog. The buttons that appear on the dialog are predefined by the TMsgDlgButtons type:
 TMsgDlgType = (mtWarning, mtError, mtInformation, mtConfirmation, mtCustom) ;
 
 TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore, mbAll, mbNoToAll, mbYesToAll, mbHelp) ;
 TMsgDlgButtons = set of TMsgDlgBtn;
 
Behind the scenes, MessageDlg creates a modal form displaying the message you provided in the Msg parameter, image defined by the DlgType parameter and a set of buttons defined by the Buttons parameter.

The result returned by the MessageDlg is of type TModalResult (basically an integer value). A value of mrCancel would be returned if the user has clicked the Cancel button; mrAll if the user has clicked the All button, and so on.

   ModalResults: array[TMsgDlgBtn] of Integer = (
     mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll, mrNoToAll, mrYesToAll, 0) ;
 

What if Closed Using "X"

The modal form displayed by a call to MessageDlg, in its title area displays the standard Windows "X" button to allow the user to close the dialog by NOT clicking on any of the buttons you have included in the dialog.

Suppose you are calling the MessageDlg function as:

 if mrNo = MessageDlg('Destroy all data?', mtWarning, [mbYes, mbNo], -1, mbNo) then
   Exit
 else
 begin
   //destroy all files
 end;
 
In the above call, the mbNo ("NO") button is set as default / focused.

Do you know what will happen if the user decides to close the dialog by clicking on the "X" button? Will "Exit" be executed? Will all the files be destroyed?

Yes, all the files will get destroyed as the result returned by the MessageDlg will be mrCancel!!

Yes, mrCancel, you have included mbYes and mbNo, but the result will be mrCancel!

MessageDlgEx with Default Button and Close Button Value

Here's a custom implementation of the MessageDlg function named MessageDlgEx. MessageDlgEx allows you to specify the default / focused button but also what is the result of closing the dialog by clicking on the X button.
 function MessageDlgEx(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; FocusBtn, CloseBtn: TMsgDlgBtn; HelpCtx: Longint): Integer;
 const
   ModalResults: array[TMsgDlgBtn] of Integer = (mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll, mrNoToAll, mrYesToAll, 0) ;
 begin
   with CreateMessageDialog(Msg, DlgType, Buttons, FocusBtn) do
   try
     HelpContext := HelpCtx;
     Position := poScreenCenter;
     Result := ShowModal;
 
     //if there's a cancel button, ignore CloseBtn.
     if (result = mrCancel) AND (NOT (mbCancel in Buttons)) then result := ModalResults[CloseBtn];
   finally
     Free;
   end;
 end;
 
Note: if the Cancel button is included in the Buttons parameter, FocusBtn will be ignored - as there's no way to know if mrCancel is the result of clicking on the mbCancel button or the X button.

MessageDlgEx uses CreateMessageDialog to create a dialog that looks like the one created using the "normal" MessageDlg function.

Finally, here's the above dialog again:

 if mrNo = MessageDlgEx('Destroy all data?'+ #13#10 + 'Don''t click the X button!',mtWarning,[mbYes, mbNo], mbNo, mbNo, -1) then
   Exit
 else
 begin
   //destroy all files - will not happen if [x] clicked
 end;
 
No need to worry any more :) There's a default button for users that are too fast and the Closed value for those that even do not read the messages in the dialogs :)

Note: Here's Delphi 7 version (CreateMessageDialog in Delphi 7 does not have the DefaultButton parameter):

 //delphi 7 version
 function MessageDlg(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; FocusBtn, CloseBtn: TMsgDlgBtn; HelpCtx: Longint): Integer;
 const
   ModalResults: array[TMsgDlgBtn] of Integer = (mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll, mrNoToAll, mrYesToAll, 0) ;
   ButtonNames: array[TMsgDlgBtn] of string = ( 'Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'NoToAll', 'YesToAll', 'Help') ;
 var
   Btn: TComponent;
 begin
   with CreateMessageDialog(Msg, DlgType, Buttons) do
   try
     HelpContext := HelpCtx;
     Position := poScreenCenter;
 
     Btn := FindComponent(ButtonNames[FocusBtn]) ;
     if (Btn <> nil) and (Btn is TWinControl) then
       ActiveControl := Btn as TWinControl;
 
     result := ShowModal;
 
     //if there's a cancel button, ignore CloseBtn.
     if (result = mrCancel) AND (NOT (mbCancel in Buttons)) then result := ModalResults[CloseBtn];
   finally
     Free;
   end;
 end;