继承一个界面控件,给它增加功能,但继承的类仍然用父类的名字

这个标题看起来有点不好理解。

问题和解决方法来自这里:https://blog.grijjy.com/2018/01/26/mvvm-starter-kit-part-3-of-3/

问题简述:

0. 传统做法:继承一个控件,取一个新的名字,然后把它安装到 IDE 里面,需要用的时候,从控件托盘里把这个新做的控件找出来,拖到界面上。

1. FireMonkey 的控件,它的 Style 利用了控件的类名。如果新的类名,搞 Style 会比较麻烦。

2. 安装一个新的控件到 IDE 里面也比较麻烦。

解决办法:

从原有控件继承,但子类依然用原有控件的名字。设计时仍然从控件托盘拖原有控件到界面上。然后在 use 里面加上对新的控件的单元的引用。编译的程序,这个控件已经是增加了新功能的新控件。

实例:

我自己模仿这个方法,自己写了一个测试程序,测试上述办法是成功的。测试程序的做法如下:

1. 新起一个 FMX 工程,保存到一个目录底下。这时候我们有一个 Form1。

2. 拖一个 TEdit 和 一个 TButton 到这个 Form1 上面,我们有了 Edit1 和 Button1;

3. 新建一个单元用于接口方法定义,如下:

unit MyIntf;

interface

uses System.SysUtils, System.Types, System.Classes;

type
  IMyTest = interface
    ['{6CCACE8D-9817-4561-9272-D3743B1090AC}']
    procedure Hello(Sender: TObject);
  end;

implementation

end.

4. 新建一个单元用于继承的类的定义,如下:

unit MyControl;

interface

uses System.SysUtils, System.Types, System.Classes,
     FMX.Types, FMX.Controls, FMX.Edit,
     MyIntf;

type
  TEdit = class(FMX.Edit.TEdit, IMyTest)
  public
    procedure Hello(Sender: TObject);

  end;

implementation

{ TMyEdit }

procedure TEdit.Hello(Sender: TObject);
begin
  Self.Text := Self.Text + Sender.ClassName + ' - Hello';
end;

end.

注意上述代码,继承自 TEdit 的类,名字仍然是 TEdit。这里要注意。它多了一个自己定义的接口。这里为它实现一个接口方法。

5. 在 Form1 的单元里面,把这个 MyControl 单元的名字加到 use 的最后。这样,之前拖过来的 TEdit 将会是 MyControl 里面定义的这个,而不是 Delphi 原本的那个。我们在 Button1 的 OnClick 里面可以测试调用它的接口,成功。说明确实是我们自己新继承的这个。这样,UI 设计的时候直接拖 Delphi 原本的控件过来,实际运行的时候它有新的功能。也无需专门为了这个新功能的控件去另取一个类名再做 IDE 的控件安装。省了很多事。

测试单元的代码如下:

unit Unit1;
  //直接继承一个 TEdit,为继承的 Edit 增加一个接口。但是,并不用新的类名,还是用原来的 TEdit 这个类名。
  //然后无需安装新继承的控件,仍然直接拖一个原来的 TEdit 过来放到 Form 上
  //然后在 Use 里面,最后放上新继承的类的声明单元,注意顺序,一定要放到最后
  //这样,当程序运行,这个 TEdit 就已经有了新增加的接口。也就是说它的实例是新的类,而不是老的类。
  //2020-2-5
interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Edit,
  FMX.Controls.Presentation, FMX.StdCtrls, MyIntf, MyControl;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;     //直接拖过来的控件,虽然还是 TEdit,但因为在 MyControl 单元里重新声明了相同名字的 TEdit,继承了原来的 TEdit 为它增加了一个接口,程序就能直接调用到这个接口了。
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  (Edit1 as IMyTest).Hello(Self);
end;

end.
发布了116 篇原创文章 · 获赞 19 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/pcplayer/article/details/104177249