Search code examples
delphimessagebox

Stopping the ding sound when using MessageDlg in the OnCloseQuery event


I found Users were inadvertently poking the main form's system menu "X" and closing the program.

To alleviate the problem, I added code to ask the User if they were sure they wanted to close the program. Doing this solved people doing high stress event check-in from having to get help relaunching the program. A win all the way around for this program.

However, there is an annoying Ding sound whenever I use MessageDlg function in the OnCloseQuery event of the main form.

Using Delphi 10.4 Professional

File->New->"Windows VCL Application - Delphi" Place the following code in the OnCloseQuery Event

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
  iOkToClose: integer;
begin
  iOkToClose
    := MessageDlg('Do you wish to close the DertSQL program?',
                  mtConfirmation, [mbYes, mbNo], 0, mbNo);
  if iOkToClose <> mrYes then
    CanClose := FALSE
  else CanClose := TRUE;
end;

Compile and run the program then poke the system menu "X"

Question: How do I get rid of the Ding sound caused by the MessageDlg function?


Solution

  • First, let's just note that your code

    if iOkToClose <> mrYes then
      CanClose := False
    else
      CanClose := True
    

    is much better written as

    CanClose := iOkToClose = mrYes
    

    In fact, you don't even need the variable. Your entire event handler can be written simply

    CanClose :=
      MessageDlg(
        'Do you wish to close the DertSQL program?',
        mtConfirmation, [mbYes, mbNo], 0, mbNo
      ) = mrYes;
    

    Now, the beep you hear is associated with the icon, so one way to get rid of the beep is to remove the icon:

    CanClose :=
      MessageDlg(
        'Do you wish to close the DertSQL program?',
        TMsgDlgType.mtCustom, [mbYes, mbNo], 0, mbNo
      ) = mrYes;
    

    Also, there are many ways to display a message box in the VCL.

    You are currently using the MessageDlg function, which I personally am not hugely fond of.

    One alternative is the standard Win32 MessageBox function:

    CanClose :=
      MessageBox(
        Handle,
        'Do you want to close this application?',
        'My App',
        MB_ICONQUESTION or MB_YESNO
      ) = ID_YES;
    

    Here there's no beep.

    But it is even better to use the task dialog:

    var dlg := TTaskDialog.Create(Self);
    try
      dlg.Caption := 'My App';
      dlg.Title := 'Do you want to exit the application?';
      dlg.MainIcon := tdiNone;
      dlg.CommonButtons := [tcbYes, tcbNo];
      CanClose := dlg.Execute and (dlg.ModalResult = mrYes);
    finally
      dlg.Free;
    end;
    

    This is particularly nice because you then follow the Win32 UI guidelines with a blue, main instruction:

    Screenshot of confirmation task dialog

    But as you can see, this is a lot of code. You probably want to make your own message dialog function based on the task dialog, like I do in my Task Dialog Message Box:

    CanClose := TD('Do you want to exit the application?')
      .YesNo
      .Execute(Self) = mrYes;