你可以覆盖对Custom TForm / Dialog的MessageDlg调用吗?

时间:2008-10-20 23:06:08

标签: delphi

我一直在使用与此类似的代码

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

在我的整个项目中,(感谢GExperts消息对话工具:))我想知道是否有人知道某种方法会覆盖调用并显示我自己的自定义表单。

我能想到的唯一方法就是制作一个像

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

并将其放在Dialogs单元之前的每个使用列表中,但是有保证的方法可以确保它使用我的代码而不是Dialogs单元代码。
我不喜欢将对话框单元复制到本地目录并对其进行更改的想法。

或者这一切都很重要,我应该使用自己的函数调用并将所有MessageDlg替换为我自己的函数。 (这不会很有趣,我已经错误地使用了MessageDlg)

5 个答案:

答案 0 :(得分:5)

顺便说一句,您希望在uses子句中的 Dialogs 单元之后添加它。

我认为你有三个选择:

  1. Dialogs 单元之后添加您自己的单元,该单元具有名为MessageDlg的方法并具有相同的签名以创建您自己的表单。
  2. 或者创建一个全新的方法或一组方法,使用您自己的表单创建特定的对话框。
  3. 进行全球搜索&将 MessageDlg 替换为 DarkAxi0mMessageDlg ,然后将DarkAxi0mDialogs单位添加到uses子句中。
  4. 第一个是有问题的,因为你可能会错过一个单元并仍然得到旧的MessageDlg。第二个需要更多的使用,但从长远来看提供了更好的灵活性。第三个可能是最简单的,也是最不利的。确保在执行替换之前进行备份,然后使用diff工具(如Beyond Compare)检查更改。

答案 1 :(得分:2)

我建议你将MessageDlg封装在自己的程序中,这样一来,如果你改变你的程序,你的所有Message对话框都会被更改,你就会保持标准。

示例:创建一些程序,如Alert(),Error(),Warning()等。如果您需要更改错误消息外观,则只需在一个地方执行此操作。

有一天,您可能想要在错误消息中添加图片,提醒......无论如何,谁知道?

答案 2 :(得分:2)

您可以使用TextPad之类的工具在文件夹和子文件夹中搜索/替换字符串的所有实例。因此,我建议您将“MessageDlg(”替换为“MyMessageDlg”(以便您可以随意自定义。应该花费全部5分钟。

我认为这会导致您在创建替换时遇到问题,并将其命名,因为它目前与VCL冲突。

答案 3 :(得分:0)

您可以劫持MessageDlg函数并使其指向您自己的MyMessageDlg函数(具有相同的签名)但我认为它对所有解决方案来说都是最不安全的。
一个糟糕的黑客代替清洁代码IMO。

保存MessageDlg的原始操作码(由编译器生成的asm)
快速跳转到MyMessageDlg代码
...然后对MessageDlg的任何调用将实际执行您的代码...
将原始代码恢复为MessageDlg
MessageDlg现在照常运行

它有效,但应该保留用于绝望的情况 ......

答案 4 :(得分:0)

我基于MessageDlg创建了一个MessageDlgEx函数,并将其放入我的一个“库”文件中,以便我的所有应用程序都可以使用它。我的功能允许你指定默认&取消按钮,给出按钮文本等。修改/替换内置功能是一种不好的做法。我仍然使用内置功能,但在需要更多功能的情况下,请保留此功能。

FYI - 该函数返回按下的按钮数。第一个按钮是1.按关闭导致返回值为0.按钮没有字形。

我已经用了大约5年了它很适合我。

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;
相关问题