简体   繁体   English

替换delphi中的组件类

[英]Replacing a component class in delphi

I know I've seen an example somewhere of a hack to define a custom version of an existing VCL component, like TButton or TEdit, with the same class name and do something to make it so that the DFM streamer will instantiate your version instead of the original.我知道我在某处看到了一个 hack 的例子,它定义了一个现有 VCL 组件的自定义版本,比如 TButton 或 TEdit,具有相同的类名,并做一些事情来使它成为这样,这样 DFM 流媒体将实例化你的版本而不是原本的。 Unfortunately, I'm in a situation where I need to be able to do that and I can't find the write-up.不幸的是,我处于一种需要能够做到这一点的情况,但我找不到相关文章。 Does anyone know where to find information on how to accomplish this?有谁知道在哪里可以找到有关如何完成此操作的信息?

In your form you can override the ReadState method like so:在您的表单中,您可以像这样覆盖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;

There are likely numerous other ways to do this, but this is how I do it!可能有很多其他方法可以做到这一点,但我就是这样做的!

EDIT: Inspecting TReader.GetFieldClass(Instance: TObject; const ClassName: string) suggests the hack that Mason recalls.编辑:检查TReader.GetFieldClass(Instance: TObject; const ClassName: string)建议梅森回忆的黑客。 The first line sets ClassType := Instance.ClassType .第一行设置ClassType := Instance.ClassType So I suspect that by changing the declaration in the pas file from Button1: TButton to Button1: MyUnit.TButton will result in your button being created.所以我怀疑通过将 pas 文件中的声明从Button1: TButton更改为Button1: MyUnit.TButton将导致您的按钮被创建。 Or perhaps the hack was to add MyUnit to the uses clause right at the end so that your version of TButton is the one that is in scope.或者也许黑客是在MyUnit的使用子句中添加MyUnit ,以便您的 TButton 版本在范围内。 However, none of this sounds very practical.然而,这些听起来都不是很实用。

I guess what you're trying to remember is an "interposer class" : inheriting a class giving the same name as the ancestor, by prefixing the ancestor's unit name.我猜你想记住的是一个“中介类” :通过在祖先的单位名称前加上前缀来继承一个与祖先同名的类。 Since the class name is not changed, the dfm streaming mechanism is not disturbed.由于类名没有改变,dfm 流机制不会受到干扰。 Would only affect the unit the class is re-declared in, unless it is put in a separate unit and that unit is included in the uses section after the base class'es.只会影响重新声明类的单元,除非它被放在一个单独的单元中并且该单元包含在基类之后的使用部分中。 Obviously, you cannot have published properties in an interposed class.显然,您不能在插入的类中发布属性。

type
  TButton = class(stdctrls.TButton)
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    [...]
  private

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM