這個標題看起來有點不好理解。
問題和解決方法來自這裏: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.