我知道我已经看到一个黑客的例子来定义现有VCL组件的自定义版本,比如TButton或TEdit,具有相同的类名并做一些事情来使DFM流媒体实例化你的版本而不是原始版本。不幸的是,我处于一种我需要能够做到这一点的情况,我找不到写作。有谁知道在哪里可以找到有关如何实现这一目标的信息?
答案 0 :(得分:19)
在表单中,您可以覆盖ReadState
方法,如下所示:
type
TMyForm = class(TForm)
protected
procedure ReadState(Reader: TReader); override;
end;
procedure TMyForm.ReadState(Reader: TReader);
begin
Reader.OnFindComponentClass := FindComponentClass;
inherited;
end;
procedure TMyForm.FindComponentClass(Reader: TReader; const ClassName: string;
var ComponentClass: TComponentClass);
begin
if ComponentClass=TButton then begin
ComponentClass := TMySuperDuperButton;
end else if ComponentClass=TEdit then begin
ComponentClass := TMyTotallyAwesomeEdit;
end;
end;
可能有很多其他方法可以做到这一点,但这就是我这样做的方式!
编辑:检查TReader.GetFieldClass(Instance: TObject; const ClassName: string)
表明了梅森回忆起的黑客行为。第一行设置ClassType := Instance.ClassType
。所以我怀疑通过将pas文件中的声明从Button1: TButton
更改为Button1: MyUnit.TButton
将导致您的按钮被创建。或者也许黑客是将MyUnit
添加到最后的uses子句中,以便您的TButton版本是范围内的那个。但是,这听起来都不是很实用。
答案 1 :(得分:11)
我猜你要记住的是"interposer class":继承一个与祖先同名的类,通过在祖先的单位名称前加上前缀。由于类名未更改,因此dfm流机制不会受到干扰。只会影响该类重新声明的单位,除非它被放在一个单独的单元中,并且该单元包含在基类之后的使用部分中。显然,您不能在插入的类中发布属性。
type
TButton = class(stdctrls.TButton)
protected
procedure CreateParams(var Params: TCreateParams); override;
end;
TForm1 = class(TForm)
Button1: TButton;
[...]
private