这个标题看起来有点不好理解。
问题和解决方法来自这里: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.