tags:

views:

684

answers:

5

I have been using code similar to this

MessageDlg('', mtWarning, [mbOK], 0);

throughout my project, (thanks to the GExperts Message Dialog tool :) ) and i was wondering if anyone knows of a way do override the call and show my own custom Form.

The only way i can think to do it its make a New Form with something like

function MessageDlg(const Msg: string; DlgType: TMsgDlgType;
  Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
begin
  //show my own code here
end;

and put it each of my uses lists before the Dialogs unit but is there a guaranteed way to make sure it uses my code not the Dialogs unit Code.
I don't like the idea of copying the dialogs unit to a local dir and making changes to it.

Or is this all to much work and should i just use my own function call and replace all the MessageDlg with my own. (which would not be fun, ive prob used MessageDlg too much)

+2  A: 

I would recommend you to encapsulate the MessageDlg inside of you own procedures, this way if you change your procedures all your Message dialogs will be changed and you keep a standard.

Example: Create some procedures like, Alert(), Error(), Warning(), etc. If you ever need to change your error message looks, you need to do it only in one place.

Someday you might want to add a picture to your error messages, alerts... whatever, who knows?

Fabio Gomes
+2  A: 

You can use a tool like TextPad to search/replace all instances of a string across folders and subfolders. So, I would suggest that you replace "MessageDlg(" with "MyMessageDlg(" so that you can customize it at will. Should take all of 5 minutes.

I think it would cause you problems to create a replacement and leave it named as it is currently in conflict with the VCL.

Argalatyr
Not to mention confusing for maintenance programmers!
Blorgbeard
+3  A: 

BTW, you want to add it after the Dialogs unit in your uses clause.

You have three choices in my opinion:

  1. Add your own unit after the Dialogs unit that has a method called MessageDlg and has the same signature to create your own form.
  2. Or create a whole new method, or set of methods, that creates specific dialogs using your own form.
  3. Do a global Search & Replace for MessageDlg with DarkAxi0mMessageDlg and then add your DarkAxi0mDialogs unit to your uses clause.

The first one is problematic because you might miss a unit and still get the old MessageDlg. The second one takes a lot more use, but provides better flexibility in the long run. The third one is probably the easiest and with the least downsides. Make sure you backup before doing the replace, and then use a diff tool (like Beyond Compare) to check your changes.

Jim McKeeth
Also another use for Sync Edit if you have alot of them in a file, just find the first one, select it through the end of a file and sync edit away.
skamradt
GExperts project grep search does a good job of assisting with finding all the references.
skamradt
A: 

You can hijack the MessageDlg function and make it point to your own MyMessageDlg function (with same signature) but I think it would the least safe of all the solutions.
A bad hack in lieu of clean code IMO.

Save the original opcodes of MessageDlg (asm generated by the compiler)
Put a hard jump to your MyMessageDlg code
...then any call to MessageDlg will actually execute YOUR code ...
Restore the original code to MessageDlg
MessageDlg now behaves as usual

It works but should be reserved for desperate situations...

François
A: 

i made a MessageDlgEx function based on MessageDlg and dropped it into one of my "library" files so all my apps can use it. my function allows you to specify default & cancel buttons, give button texts, etc. it'd be a bad practice to modify/replace the built-in function. i still use the built-in function but keep this function on hand for situations where a little more is needed.

FYI--the function returns the number of the button pressed. the first button is 1. pressing Close causes a return value of 0. the buttons have no glyphs.

i have been using this for about 5 years & it's served me well.

function MessageDlgEx(Caption, Msg: string; AType: TMsgDlgType;
                      AButtons: array of string;
                      DefBtn, CanBtn: Integer; iWidth:integer=450;bCourier:boolean=false): Word;
const
  icMin=50;
  icButtonHeight=25;
  icInterspace=10;
  icButtonResultStart=100;
  icFirstButtonReturnValue=1;
var
  I, iButtonWidth, iAllButtonsWidth,
  iIconWidth,iIconHeight:Integer;
  LabelText:String;
  Frm: TForm;
  Lbl: TLabel;
  Btn: TBitBtn;
  Glyph: TImage;
  FIcon: TIcon;
  Rect:TRect;
  Caption_ca:Array[0..2000] of Char;
begin
  { Create the form.}
  Frm := TForm.Create(Application);
  Frm.BorderStyle := bsDialog;
  Frm.BorderIcons := [biSystemMenu];
  Frm.FormStyle := fsStayOnTop;
  Frm.Height := 185;
  Frm.Width := iWidth;
  Frm.Position := poScreenCenter;
  Frm.Caption := Caption;
  Frm.Font.Name:='MS Sans Serif';
  Frm.Font.Style:=[];
  Frm.Scaled:=false;

  if ResIDs[AType] <> nil then
    begin
      Glyph := TImage.Create(Frm);
      Glyph.Name := 'Image';
      Glyph.Parent := Frm;

      FIcon := TIcon.Create;
      try
        FIcon.Handle := LoadIcon(HInstance, ResIDs[AType]);
        iIconWidth:=FIcon.Width;
        iIconHeight:=FIcon.Height;
        Glyph.Picture.Graphic := FIcon;
        Glyph.BoundsRect := Bounds(icInterspace, icInterspace, FIcon.Width, FIcon.Height);
      finally
        FIcon.Free;
      end;
    end
    else
    begin
      iIconWidth:=0;
      iIconHeight:=0;
    end;

  { Loop through buttons to determine the longest caption. }
  iButtonWidth := 0;
  for I := 0 to High(AButtons) do
    iButtonWidth := Max(iButtonWidth, frm.Canvas.TextWidth(AButtons[I]));

  { Add padding for the button's caption}
  iButtonWidth := iButtonWidth + 18;

  {assert a minimum button width}
  If iButtonWidth<icMin Then
    iButtonWidth:=icMin;

  { Determine space required for all buttons}
  iAllButtonsWidth := iButtonWidth * (High(AButtons) + 1);

  { Each button has padding on each side}
  iAllButtonsWidth := iAllButtonsWidth +icInterspace*High(AButtons);

  { The form has to be at least as wide as the buttons with space on each side}
  if iAllButtonsWidth+icInterspace*2 > Frm.Width then
    Frm.Width := iAllButtonsWidth+icInterspace*2;

  if Length(Msg)>sizeof(Caption_ca) then
    SetLength(Msg,sizeof(Caption_ca));

  { Create the message control}
  Lbl := TLabel.Create(Frm);
  Lbl.AutoSize := False;
  Lbl.Left := icInterspace*2+iIconWidth;
  Lbl.Top := icInterspace;
  Lbl.Height := 200;
  Lbl.Width := Frm.ClientWidth - icInterspace*3-iIconWidth;
  Lbl.WordWrap := True;
  Lbl.Caption := Msg;
  Lbl.Parent := Frm;

  if bCourier then
    lbl.Font.Name:='Courier New';

  Rect := Lbl.ClientRect;
  LabelText:=Lbl.Caption;
  StrPCopy(Caption_ca, LabelText);

  Lbl.Height:=DrawText(Lbl.Canvas.Handle,
                       Caption_ca,
                       Length(LabelText),
                       Rect,
                       DT_CalcRect or DT_ExpandTabs or DT_WordBreak Or DT_Left);


  If Lbl.Height<iIconHeight Then
    Lbl.Height:=iIconHeight;

  { Adjust the form's height accomodating the message, padding and the buttons}
  Frm.ClientHeight := Lbl.Height + 3*icInterspace + icButtonHeight;

  { Create the pusbuttons}
  for I := 0 to High(AButtons) do
    begin
      Btn := TBitBtn.Create(Frm);
      Btn.Height := icButtonHeight;
      Btn.Width := iButtonWidth;
      Btn.Left:=((Frm.Width-iAllButtonsWidth) Div 2)+I*(iButtonWidth+icInterspace);
      Btn.Top := Frm.ClientHeight - Btn.height-icInterspace;
      Btn.Caption := AButtons[I];
      Btn.ModalResult := I + icButtonResultStart + icFirstButtonReturnValue;
      Btn.Parent := Frm;

      If I=DefBtn-1 Then
        Begin
          Frm.ActiveControl:=Btn;
          Btn.Default:=True;
        End
        Else
        Btn.Default:=False;

      If I=CanBtn-1 Then
        Btn.Cancel:=True
        Else
        Btn.Cancel:=False;
    end;

  Application.BringToFront;

  Result := Frm.ShowModal;

  {trap and convert user Close into mrNone}
  If Result=mrCancel Then
    Result:=mrNone
    Else
    If Result>icButtonResultStart Then
      Result:=Result - icButtonResultStart
      Else
      Exception.Create('Unknown MessageDlgEx result');

  Frm.Free;
end;
X-Ray