【问题标题】:Replacing a component class in delphi替换delphi中的组件类
【发布时间】:2011-06-08 19:45:09
【问题描述】:

我知道我在某处看到了一个 hack 示例,用于定义具有相同类名的现有 VCL 组件(如 TButton 或 TEdit)的自定义版本,并做一些事情以使 DFM 流媒体实例化您的版本代替原版。不幸的是,我处于需要能够做到这一点的情况下,但我找不到文章。有谁知道在哪里可以找到有关如何完成此操作的信息?

【问题讨论】:

标签: delphi controls


【解决方案1】:

在您的表单中,您可以像这样覆盖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 版本是范围内的版本。然而,这些听起来都不是很实用。

【讨论】:

  • 我可能会弄错,但我也会添加对 ClassName 的检查,而不仅仅是 ComponentClass。以防万一 Delphi 2 和 Delphi XE 之间发生了变化;)
  • 有趣。我还没有听说过这个版本,但这可能适用于我需要做的事情。
  • @Mason 我的应用程序中的所有表单都派生自 TMyForm。这是我向大家推荐的东西!
  • @Mason 否则你可以像 Andreas Hausladen 那样在运行时修补它
  • 恭喜你,@大卫。顺便说一句,如果你继续这样下去,你很快就会在所有列表中名列前茅! stackoverflow.com/tags/delphi/topusers
【解决方案2】:

我猜你想记住的是"interposer class":继承一个与祖先同名的类,方法是在祖先的单位名称前加上前缀。由于类名没有改变,dfm流机制没有被打乱。只会影响重新声明类的单元,除非它被放在一个单独的单元中,并且该单元包含在基类之后的使用部分中。显然,您不能在插入的类中发布属性。

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

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

【讨论】:

  • 是的,我就是这么想的。但事实证明,大卫的解决方案对我试图解决的问题更有效。
猜你喜欢
  • 2023-03-03
  • 2011-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-18
相关资源
最近更新 更多