MessageDlg buttons not in right order

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
YES   ABORT   IGNORE

when it should be:

YES   IGNORE  ABORT

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?

Thanks!
    Shawn
shawn857Asked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
Geert GruwezConnect With a Mentor Oracle dbaCommented:
it processes them like this in the source of CreateMessageDialog

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

Open in new window


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

interface

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

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

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

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


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

end.

Open in new window

0
 
jimyXConnect With a Mentor Commented:
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 }

type
  TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore,
    mbAll, mbNoToAll, mbYesToAll, mbHelp);
  TMsgDlgButtons = set of TMsgDlgBtn;
...
var
  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,
    @SMsgDlgHelp);
  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.
type
  TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbRetry, mbIgnore, mbAbort,
    mbAll, mbNoToAll, mbYesToAll, mbHelp);
  TMsgDlgButtons = set of TMsgDlgBtn;
...
var
  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,
    @SMsgDlgHelp);
  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.
0
 
shawn857Author Commented:
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.

Thanks!
   Shawn
0
All Courses

From novice to tech pro — start learning today.