?
Solved

MessageDlg buttons not in right order

Posted on 2014-01-20
3
Medium Priority
?
833 Views
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
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
0
Comment
Question by:shawn857
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
3 Comments
 
LVL 24

Assisted Solution

by:jimyX
jimyX earned 1000 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 }

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
 
LVL 38

Accepted Solution

by:
Geert Gruwez earned 1000 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
      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
 

Author Closing Comment

by:shawn857
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.

Thanks!
   Shawn
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

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…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses
Course of the Month13 days, 11 hours left to enroll

801 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