Generic dialog with custom captions for buttons

21,066

Solution 1

you can use this code:

function MyMessageDlg(CONST Msg: string; DlgTypt: TmsgDlgType; button: TMsgDlgButtons;
  Caption: ARRAY OF string; dlgcaption: string): Integer;
var
  aMsgdlg: TForm;
  i: Integer;
  Dlgbutton: Tbutton;
  Captionindex: Integer;
begin
  aMsgdlg := createMessageDialog(Msg, DlgTypt, button);
  aMsgdlg.Caption := dlgcaption;
  aMsgdlg.BiDiMode := bdRightToLeft;
  Captionindex := 0;
  for i := 0 to aMsgdlg.componentcount - 1 Do
  begin
    if (aMsgdlg.components[i] is Tbutton) then
    Begin
      Dlgbutton := Tbutton(aMsgdlg.components[i]);
      if Captionindex <= High(Caption) then
        Dlgbutton.Caption := Caption[Captionindex];
      inc(Captionindex);
    end;
  end;
  Result := aMsgdlg.Showmodal;
end;

For example:

MyMessageDlg('Hello World!', mtInformation, [mbYes, mbNo],
      ['Yessss','Noooo'], 'New MessageDlg Box'):

Solution 2

How about something like this:

type
  TButtonInfo = record
    MsgDlgBtn: TMsgDlgBtn;
    Caption: string;
  end;

function ButtonInfo(MsgDlgBtn: TMsgDlgBtn; const Caption: string): TButtonInfo;
begin
  Result.MsgDlgBtn := MsgDlgBtn;
  Result.Caption := Caption;
end;

const
  ModalResults: array[TMsgDlgBtn] of Integer = (
    mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll, mrNoToAll,
    mrYesToAll, 0, mrClose);

function FindDialogButton(Form: TForm; MsgDlgBtn: TMsgDlgBtn): TButton;
var
  i: Integer;
  Component: TComponent;
begin
  for i := 0 to Form.ComponentCount-1 do begin
    Component := Form.Components[i];
    if Component is TButton then begin
      if TButton(Component).ModalResult=ModalResults[MsgDlgBtn] then begin
        Result := TButton(Component);
        exit;
      end;
    end;
  end;
  Result := nil;
end;

function MessageDlg(
  const aMsg: string;
  aDlgType: TMsgDlgType;
  const Buttons: array of TButtonInfo;
  aDefault: TMsgDlgBtn
): TModalResult;
var
  i: Integer;
  MsgDlgButtons: TMsgDlgButtons;
  vDlg: TForm;
begin
  MsgDlgButtons := [];
  for i := low(Buttons) to high(Buttons) do begin
    Assert(not (Buttons[i].MsgDlgBtn in MsgDlgButtons));//assert uniqueness
    Include(MsgDlgButtons, Buttons[i].MsgDlgBtn);
  end;
  vDlg := CreateMessageDialog(aMsg, aDlgType, MsgDlgButtons, aDefault);
  try
    for i := low(Buttons) to high(Buttons) do begin
      FindDialogButton(vDlg, Buttons[i].MsgDlgBtn).Caption := Buttons[i].Caption;
    end;
    vDlg.Position := poDefaultPosOnly;
    Result := vDlg.ShowModal;
  finally
    vDlg.Free;
  end;
end;

procedure Test;
begin
  MessageDlg(
    'Really quit application ?',
    mtWarning,
    [ButtonInfo(mbNo, 'Do&n''t save'), ButtonInfo(mbCancel, '&Cancel'), ButtonInfo(mbYes,'&Save')],
    mbYes
  );
end;

enter image description here

Solution 3

I write this code: (I am from Croatia, so the texts are in Croatian)

function MojDijalog(const Msg, Capt: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons;
  DefaultButton: TMsgDlgBtn): TModalResult;
var
  dlg : TForm;
begin
  dlg := CreateMessageDialog(Msg, DlgType, Buttons, DefaultButton) ;
  with dlg do begin
     Caption := Capt;
     FormStyle := fsStayOnTop;
     ( FindComponent( 'OK' ) as TButton ).Caption := 'U redu' ;
     ( FindComponent( 'Cancel' ) as TButton ).Caption := 'Odustani' ;
     ( FindComponent( 'Yes' ) as TButton ).Caption := 'Da' ;
     ( FindComponent( 'No' ) as TButton ).Caption := 'Ne' ;
      ( FindComponent( 'Help' ) as TButton ).Caption := 'Pomoć' ;
     ( FindComponent( 'Close' ) as TButton ).Caption := 'Zatvori' ;
     ( FindComponent( 'Ignore' ) as TButton ).Caption := 'Zanemari' ;
     ( FindComponent( 'Retry' ) as TButton ).Caption := 'Pokušaj ponovo' ;
     ( FindComponent( 'Abort' ) as TButton ).Caption := 'Prekini' ;
     ( FindComponent( 'All' ) as TButton ).Caption := 'Sve' ;
  end;
  Result := dlg.ShowModal;
end;

Example of use :

if MojDijalog('Obrisati zapis ?','Upit za brisanje',mtConfirmation,mbYesNo,mbNo) = mrNo then
    begin
         Abort;
    end;
Share:
21,066

Related videos on Youtube

Roland Bengtsson
Author by

Roland Bengtsson

Middle aged man who grown up in Skattagård outside Falkenberg, Sweden Now I live in Nedervetil, Finland and work as Delphi developer on Attracs

Updated on July 09, 2022

Comments

  • Roland Bengtsson
    Roland Bengtsson almost 2 years

    I know this issue have been up since before (ex. Best way to show customized message dialogs), but I still don't find what I want.

    I started like this:

    class function TAttracsForm.MessageDlg(const aMsg: string; aDlgType: TMsgDlgType; Buttons: TMsgDlgButtons; aCaptions: array of String; aDefault: TMsgDlgBtn): TModalResult;
    var
      vDlg: TForm;
      i: Integer; 
    begin
      if aButtons.Count = aCaptions.Count then
      begin
        vDlg := CreateMessageDialog(aMsg, aDlgType, Buttons);
        try
          for i := 0 aCaptions.Count - 1 do
            TButton(vDlg.FindComponent(Buttons[i].Caption)).Caption := aCaptions[i]; 
    
          vDlg.Position := poDefaultPosOnly;
          Result := vDlg.ShowModal;
        finally
          vDlg.Free;
        end;
      end;
    end;
    

    And the call would look like:

    if (MessageDlg('Really quit application ?', mtWarning, 
           [mbNo, mbCancel, mbYes], {'No save', 'Cancel', 'Save'}) = mrYes) then
    

    But the above code of course don't compile. I don't know how to get one item of an set in the loop and how to get the total count of it in the beginning.

    • Uli Gerhardt
      Uli Gerhardt about 13 years
      Maybe you can use TTaskDialog or one of the pre-Vista capable emulations.
  • David Heffernan
    David Heffernan about 13 years
    Why not? Is it because I used accelerator keys perhaps? Also, "This doesn't work" isn't a very good error report..... ;-)
  • Leslie
    Leslie about 13 years
    @David - that's the error message most of our users report! LOL
  • Andreas Rejbrand
    Andreas Rejbrand about 13 years
    I think you might not want FindComponent(Buttons[i].Caption). It is pretty unlikely that the unmodified dialog has a control named 'Do&nt'' save'.
  • Andreas Rejbrand
    Andreas Rejbrand about 13 years
    It's a bit interesting that you get upvotes even though your code doesn't work! Clearly, people aren't actually trying the code before upvoting! Still, your code is beautiful, and deserves a lot of upvotes as soon as the bug is fixed.
  • David Heffernan
    David Heffernan about 13 years
    @Andreas @Roland Code works now!! Pretty hacky, but there you go. Would be quite easy to roll your own Task Dialog type form.
  • David Heffernan
    David Heffernan about 13 years
    @Andreas Thanks! Not sure I'd say beautiful though!!
  • Andreas Rejbrand
    Andreas Rejbrand about 13 years
    @David: Interesting, your solution is identical to the one I just wrote, that is, using a conversion array between buttons and modal results.
  • David Heffernan
    David Heffernan about 13 years
    @Andreas It's funny, I saw all the other issues with the code, but assumed the FindComponent stuff was fine since I never do stuff like that anyway!
  • Roland Bengtsson
    Roland Bengtsson about 13 years
    David I tried the code and it doesn't work because of the reason Andreas said. FindComponent(Buttons[i].Caption) may be wrong. But I think the problem is solved anyway even if it isn't exactly as I want it. And the upvote is just for a good try for you David... :)
  • David Heffernan
    David Heffernan about 13 years
    @Roland The code works perfectly. You are probably running the original version. I edited it yesterday and now it works. As you can see above, there is no call to FindComponent. This is your answer.
  • QMaster
    QMaster over 8 years
    Work perfectly but in example must use , and not ; for dividing parameters and you can check it with normal MessageDlg results. So use it as this way: if MyMessageDlg('Hello World!', mtInformation, [mbYes, mbNo], ['Yessss','Noooo'], 'New MessageDlg Box') = mrYes then Begin .... End
  • yonojoy
    yonojoy about 8 years
    @Holmes For a solution with Firemonkey have a look at this answer.
  • David Heffernan
    David Heffernan about 6 years
    @ShahramBanazadeh What do you mean?
  • Shahram Banazadeh
    Shahram Banazadeh about 6 years
    @DavidHeffernan I can not see routine that sets default (selected ) button passed by last parameter(adefault) .not implemented ?
  • David Heffernan
    David Heffernan about 6 years
    @Shahram How it is set? Again I don't know what you mean. Why don't you read the code and see how the parameter is used?
  • Shahram Banazadeh
    Shahram Banazadeh about 6 years
    @DavidHeffernan Because it is not used. I was wondering if I am missing some thing. aDefault: TMsgDlgBtn is not used in body.
  • David Heffernan
    David Heffernan about 6 years
    I see. I've fixed it now.
  • Uli Gerhardt
    Uli Gerhardt over 5 years
    (Posted for [stackoverflow.com/users/6227080/nervouz](Nervouz) who can't comment himself.) Nice code @DavidHeffernan! It`s work for me. I can't anwer on your post. There are some way to make the length of buttons "customized" or "Justified"? Thank you!
  • David Heffernan
    David Heffernan over 5 years
    @computer the question is about delphi
  • computerjulian
    computerjulian over 5 years
    Unfortunately, this does not work in Lazarus 1.8.0. The custom caption does not affect the actual button caption, ist just 'yes' and 'no.'
  • Jerry Dodge
    Jerry Dodge almost 4 years
    Why set it to bdRightToLeft? It ends up destroying the text.
  • Mohammad
    Mohammad almost 4 years
    @JerryDodge Because it was supposed to run for Right to Left languages like Persian ;) For Left to Right languages, you don't need.

Related