【问题标题】:Can you override MessageDlg calls to a Custom TForm/Dialog?您可以覆盖对自定义 TForm/Dialog 的 MessageDlg 调用吗?
【发布时间】:2010-09-18 05:28:23
【问题描述】:

我一直在使用类似的代码

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 太多了)

【问题讨论】:

    标签: delphi


    【解决方案1】:

    顺便说一句,您想将它添加到您的 uses 子句中的 Dialogs 单元之后。

    在我看来你有三个选择:

    1. Dialogs 单元之后添加您自己的单元,该单元有一个名为 MessageDlg 的方法,并且具有相同的签名来创建您自己的表单。
    2. 或者创建一个全新的方法或一组方法,使用您自己的表单创建特定的对话框。
    3. 使用 DarkAxi0mMessageDlgMessageDlg 进行全局搜索和替换,然后将 DarkAxi0mDialogs 单元添加到 uses 子句中。

    第一个是有问题的,因为您可能会错过一个单元并仍然得到旧的 MessageDlg。第二个需要更多的使用,但从长远来看提供了更好的灵活性。第三个可能是最简单且缺点最少的。确保在替换之前进行备份,然后使用差异工具(如 Beyond Compare)检查您的更改。

    【讨论】:

    • 如果文件中有很多同步编辑,也可以使用同步编辑,只需找到第一个,从文件末尾选择它并同步编辑。
    • GExperts 项目 grep 搜索在帮助查找所有参考文献方面做得很好。
    【解决方案2】:

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

    示例:创建一些过程,如 Alert()、Error()、Warning() 等。如果您需要更改错误消息的外观,只需在一个地方进行。

    有一天,您可能想在错误消息、警报中添加图片...随便,谁知道呢?

    【讨论】:

      【解决方案3】:

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

      我认为创建替换并保留其名称会导致您出现问题,因为它目前与 VCL 冲突。

      【讨论】:

      • 更不用说维护程序员的困惑了!
      【解决方案4】:

      您可以劫持 MessageDlg 函数并使其指向您自己的 MyMessageDlg 函数(具有相同的签名),但我认为它是所有解决方案中最不安全的。
      A坏 hack 代替干净的代码 IMO。

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

      它有效,但应该在危急情况下保留...

      【讨论】:

        【解决方案5】:

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

        仅供参考——该函数返回按下按钮的编号。第一个按钮是 1。按 Close 会导致返回值 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;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-03-04
          • 1970-01-01
          • 2010-12-17
          • 2019-11-16
          • 2015-11-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多