MessageDlg buttons not in right order

Posted on 2014-01-20
Last Modified: 2014-01-21
Hi Experts, I have a 3-button MessageDlg like this:

MsgVar := MessageDlg('Problem found!'+#13#10+#13#10+
                        'Click YES to proceed and display each occurence of this.'+#13#10+
                        'Click IGNORE to proceed without showing any more occurrences.'+#13#10+
                        'Click ABORT to abort this process altogether.', mtWarning, [mbYes,mbIgnore,mbAbort], 0);

if MsgVar = mrYes then FoundDiscrepancy[i] := FALSE
else if MsgVar = mrIgnore then FoundDiscrepancy[i] := TRUE
else EXIT;

Open in new window

When it displays, it shows the 3 buttons in the wrong order. It shows them as

when it should be:


However, when I do click a button, it does seem to perform the appropriate action - it's just the order that's wrong. Any idea what would be going on?

Question by:shawn857
LVL 24

Assisted Solution

jimyX earned 250 total points
ID: 39796156
That's normal. Delphi set that order and logic, even if you tried to change them, Delphi will revert back.
Because the buttons are not actually placed in the MsgForm by the logic you think of. What Delphi does actually is looping through the array of ButtonNames and if the button is present in you MsgDlg assigned Buttons it's placed first and then proceed to the next and when found another button it will be placed until finishing the array. That's why when you put two YESes you do not get two buttons like [mbyes, mbAbort,mbIgnore,mbYes].

You have two options here, either to change "Dialogs.pas" and set that order to suit your requirement, or change the caption of the MsgDlg's Buttons in order to show the preferred order, but your buttons' actions will be different and perform different, they will perform same as in Delphi's order so 1st btn will be 'Yes' and will return "mrYes", 2nd btn will be 'Ignore' but will return "mrAbort", and finally 3rd btn 'Abort' will return "mrIgnore" so it will be confusing (very confusing) to interpret the result of the MsgDlg.

In case you want to change the Dialog's Source, here is the part you want to work with, but make sure to work on a local copy at your project folder of "Dialogs.pas" file:
Here is the order that Delphi uses:
{ Message dialog }

  TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore,
    mbAll, mbNoToAll, mbYesToAll, mbHelp);
  TMsgDlgButtons = set of TMsgDlgBtn;
  ButtonNames: array[TMsgDlgBtn] of string = (
    'Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'NoToAll',
    'YesToAll', 'Help');
  ButtonCaptions: array[TMsgDlgBtn] of Pointer = (
    @SMsgDlgYes, @SMsgDlgNo, @SMsgDlgOK, @SMsgDlgCancel, @SMsgDlgAbort,
    @SMsgDlgRetry, @SMsgDlgIgnore, @SMsgDlgAll, @SMsgDlgNoToAll, @SMsgDlgYesToAll,
  ModalResults: array[TMsgDlgBtn] of Integer = (
    mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll, mrNoToAll,
    mrYesToAll, 0);

Open in new window

And here is what you want it to be:
{ Message dialog }
// Make sure to put them all in the same order
                 // mbYes, mbNo, mbOK,....
//should parallel
               // Yes, No, OK,...
//and parallel
              // mrYes, mrNo, mrOK,...
// and so on.
  TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbRetry, mbIgnore, mbAbort,
    mbAll, mbNoToAll, mbYesToAll, mbHelp);
  TMsgDlgButtons = set of TMsgDlgBtn;
  ButtonNames: array[TMsgDlgBtn] of string = (
    'Yes', 'No', 'OK', 'Cancel', 'Retry', 'Ignore', 'Abort', 'All', 'NoToAll',
    'YesToAll', 'Help');
  ButtonCaptions: array[TMsgDlgBtn] of Pointer = (
    @SMsgDlgYes, @SMsgDlgNo, @SMsgDlgOK, @SMsgDlgCancel, @SMsgDlgRetry, @SMsgDlgIgnore,
    @SMsgDlgAbort, @SMsgDlgAll, @SMsgDlgNoToAll, @SMsgDlgYesToAll,
  ModalResults: array[TMsgDlgBtn] of Integer = (
    mrYes, mrNo, mrOk, mrCancel, mrRetry, mrIgnore, mrAbort, mrAll, mrNoToAll,
    mrYesToAll, 0);

Open in new window

If you prefer to work over the MsgBtns' caption then use this function.

The third option is to create your own MsgForm from scratch.

It is better to leave it the way it is. I am sure Delphi has got a good reason to set the order in that way. In anyways the user will eventually find those buttons and will be able to pick the suitable one to click for the action no matter what was the order of the buttons.
LVL 37

Accepted Solution

Geert Gruwez earned 250 total points
ID: 39796289
it processes them like this in the source of CreateMessageDialog

   for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
      if B in Buttons then
        LButton := TButton.Create(Result);
        with LButton do
          Name := ButtonNames[B];
          Parent := Result;

Open in new window

you could call your own function switching the button positions as you need
unit uTestEE;


  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

  TForm1 = class(TForm)
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    { Private declarations }
    { Public declarations }

  Form1: TForm1;


{$R *.dfm}

procedure SwitchPos(Button1, Button2: TButton);
var P: TPoint;
  P := Point(Button1.Left, Button1.Top);
  Button1.Left := Button2.Left;
  Button1.Top := Button2.Top;
  Button2.Left := P.X;
  Button2.Top := P.Y;

function MessageDlg(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; DoSwitchPos: Boolean = False): Integer;
  ButtonNames: array[TMsgDlgBtn] of string = (
    'Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'NoToAll',
    'YesToAll', 'Help', 'Close');
var D: TForm;
  B1, B2, B3: TButton;
  D := CreateMessageDialog(Msg, DlgType, Buttons);
    if DoSwitchPos then
      B1 := TButton(D.FindComponent(ButtonNames[mbYes]));
      B2 := TButton(D.FindComponent(ButtonNames[mbNo]));
      B3 := TButton(D.FindComponent(ButtonNames[mbIgnore]));
      SwitchPos(B1, B2);
      SwitchPos(B3, B1);
    Result := D.ShowModal;

procedure TForm1.Button2Click(Sender: TObject);
  // Original position
  MessageDlg('Yes, No, Ignore', mtWarning, [mbYes, mbNo, mbIgnore]);
  // Switched posses
  MessageDlg('No, Ignore, Yes', mtWarning, [mbNo, mbIgnore, mbYes], True);


Open in new window


Author Closing Comment

ID: 39798430
Thanks for the info guys, sounds like too much bother really and I just used the constant mbYesNoCancel option instead and that works okay for me.


Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Delphi: how to send PJL commands to printer 3 90
Delphi XE10 Round Image 2 79
control image tags in a string ? 12 111
update joined tables 2 32
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: (…
Internet Business Fax to Email Made Easy - With  eFax Corporate (, you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, f…

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now