10

On Win 7, MessageDlg shows information icon instead of confirmation icon (question mark). Here is the code:

MessageDlg('Are you sure you want to delete this file?'+ CRLF+ FileName, mtConfirmation, [mbYes, mbNo], 0)= mrYes

What am I doing wrong?

Gabriel
  • 20,797
  • 27
  • 159
  • 293

4 Answers4

20

First, notice that a simple workaround is to use the Windows API MessageBox function instead:

MessageBox(Handle, 'This is a test.', 'Test', MB_ICONQUESTION or MB_YESNO)

MessageBox

But why doesn't MessageDlg work? Well, MessageDlg does one of two possible things. It uses the Windows Vista+ Task Dialog, if possible, that is, it the OS is Windows Vista or later and themes are enabled and the UseLatestCommonDialogs global variable is true (the default). If not, the VCL actually creates a custom TForm and adds all buttons, labels, and icons manually (which is a bit odd if you ask me -- why not simply use MessageBox?).

The last approach supports the question-mark icon. Indeed, try

UseLatestCommonDialogs := false;
MessageDlg('This is a test', mtConfirmation, [mbYes, mbNo], 0);

MessageDlg

But this looks so ugly! Please don't do this! It is stupid to create a custom message dialog instead of using the native OS dialogs!

Unfortunately, however, the Task Dialog does not support the question-mark icon (as a pre-defined icon). This is not a restriction of the TTaskDialog wrapper, but a limitation of the Windows Task Dialog API. See the official documentation, for instance. There are TD_ERROR_ICON, TD_WARNING_ICON, and TD_INFORMATION_ICON, but no question-mark icon.

Of course, the Task Dialog can use any icon. For instance, you can do

if (Win32MajorVersion >= 6) and ThemeServices.ThemesEnabled then
    with TTaskDialog.Create(Self) do
      try
        Caption := 'Test';
        Title := 'Test';
        Text := 'This is a test.';
        CommonButtons := [tcbYes, tcbNo];
        CustomMainIcon.ReleaseHandle;
        CustomMainIcon.Handle := LoadIcon(0, IDI_QUESTION);
        Flags := [tfUseHiconMain];
        Execute;
      finally
        Free;
      end
  else
    MessageBox(Handle,
               'This is a test.',
               'Test',
               MB_ICONQUESTION or MB_YESNO);

Notice that I fall back on the old MessageBox should the Task Dialog API not be available.

Task Dialog

In principle, the MessageDlg function could use additional logic to handle the question-mark case separately, in a way that differs from the information, warning, and error cases. This would have made the mtConfirmation give the right icon even with the Task Dialog, at the expence of slightly more complicated, and less elegant, VCL code. Apparently, however, Embarcadero chose the simpler alternative of simply pretending that you asked for the information icon.

Still, I wonder why Microsoft chose not to include a TD_QUESTION_ICON constant in the API. Perhaps this icon is discouraged in their latest UI guidelines?

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • The `ThemeServices.ThemesEnabled` test made me chuckle. You do realise I trust that you have to do this due to a silly bug in the Delphi TTaskDialog. Task Dialog is available for Win32MajorVersion >= 6 and it works perfectly on Windows Classic. I've no idea why Embarcadero did it the way they did. As you might imagine, I use my own wrapper of the task dialog API due to such weaknesses. – David Heffernan Jun 14 '11 at 14:53
  • @David: Yes, I have never understood why themes have to be enabled (but I haven't spent any time researching the issue, either). But sure, `TTaskDialog` has a few problems. Most importantly, it virtually lacks documentation. But it also has a few bugs, for instance [this one](http://stackoverflow.com/questions/3585867/how-to-verify-if-the-checkbox-is-checked-in-a-delphi-ttaskdialog). – Andreas Rejbrand Jun 14 '11 at 15:05
  • Hi Andreas. Actually I immediately switched to MessageBox when I have seen that MessageDlg is not working. I just wanted to what I was doing wrong. Thanks for your most complete explanation. Accepted. – Gabriel Jun 14 '11 at 15:16
  • Use Flags := Flags + [tfUseHiconMain]; otherwise you loose the close button of the dialog on Windows10 :) . +1 for the answer – RBA Nov 17 '16 at 11:58
  • When you have to display longer strings, MessageBox is much better than TTaskDialog because TTaskDialog will wrap your strings too soon (its width tends to be much smaller than MessageBox 's width). – Gabriel Feb 17 '17 at 11:09
  • It is not stupid to use a custom dialog, I want to localize my program but using the WinAPI I cannot change the button texts. Changing the Windows language does not work either, the language pack might not be installed. So my own message box is the only option. – gonutz May 28 '20 at 11:53
2

If you need some Dialogs, you may take a look at our Open Source SynTaskDialog unit for Windows XP, Vista, Seven.

It will call the Native Task Dialog under Vista and Seven, and emulate it under XP. You'll have better interaction than with the standard Dialogs unit or Windows API, and will have your confirmation icon, just as expected.

Here is the result under a Windows Seven 64 bit computer:

Windows Seven

And here is the same dialog created from our Emulated pure Delphi code:

from Delphi code

Here is a selection task dialog, with "Command links" buttons, in native Seven:

Windows Seven

And here is the window as created with the VCL emulation code:

from Delphi code

Note that there is the confirmation icon. ;)

Working from Delphi 6 up to XE.

Arnaud Bouchez
  • 42,305
  • 3
  • 71
  • 159
  • Still, the programmer's interface looks easier to use than the interface of the VCL `TTaskDialog`. – Andreas Rejbrand Jun 14 '11 at 19:36
  • @Andreas Yes, the small footer icon is rendered using GDI: it's the standard dialog icon retrieved from the OS, stretched in its half size. I should use GDI+ to render it with better anti-aliasing. But I didn't want to add any further dependency to the unit, for the XP part. If you know how to retrieve a better looking half-sized icon through API, I'm your man! And yes, I tried to make the interface easier than TTaskDialog: it's not a free clone, it's a new implementation (I didn't look at VCL code, just wanted the work to be done). – Arnaud Bouchez Jun 15 '11 at 06:23
  • PS: I think the icon is looking not perfect, but acceptable. The user will understand its meaning. It's not like in the case of MessageDlg where the icon was totally wrong. – Gabriel Jun 15 '11 at 13:11
  • @Arnaud: [LoadIconWithScaleDown](http://msdn.microsoft.com/en-us/library/windows/desktop/bb775703%28v=vs.85%29.aspx) seems to do it but it's available only where TaskDialogIndirect also is available (I wonder why? ;-)) - so it's of not much use for your emulation. – Uli Gerhardt Oct 24 '11 at 12:02
  • You could solve the icon aliasing problem by using `CreateIconFromSmallerIcon` from here: http://stackoverflow.com/questions/8112953/how-do-i-load-icons-from-a-resource-without-suffering-from-aliasing/8112954#8112954 – David Heffernan Nov 14 '11 at 10:52
-1
if (Win32MajorVersion >= 6) and ThemeServices.ThemesEnabled then
    with TTaskDialog.Create(Self) do
      try
        Caption := 'Delete';
        Title := 'Are you sure to remove the minecraft?';
        Text := 'if you delete minecraft it well be gone forever.';
        CommonButtons := [tcbYes, tcbNo];
        CustomMainIcon.ReleaseHandle;
        CustomMainIcon.Handle := LoadIcon(0, IDI_QUESTION);
        Flags := [tfUseHiconMain];
        Execute;
      finally
        Free;
      end
  else
    MessageBox(Handle,
               'if you delete minecraft it well be gone forever.',
               'Are you sure to remove the minecraft?',
               MB_ICONQUESTION or MB_YESNO);
Robert
  • 7,394
  • 40
  • 45
  • 64
  • Welcome! You could make this question better in my estimation if you wrote a few sentences describing in words what you're trying to do and what your code does not do as you've written it. – josephkibe Apr 16 '21 at 03:53
-1
if MessageDlg('Are You Want To Exit And Close All Form ? ', mtConfirmation, [mbYes, mbNo] , 0) = mrYes then
begin
Main_Form.Close;
end;
toyota Supra
  • 3,181
  • 4
  • 15
  • 19
Alireza
  • 1
  • 1