您是否可以从delphi组件中删除已发布的属性,并且不会在使用该组件的表单上导致错误?

Amy*_*Amy 18 delphi

我有一个由我公司开发的组件,并希望删除一个不再需要的已发布属性,并与组件现在的工作方式发生冲突.

有没有办法删除属性,并且在加载使用该组件的表单时,在运行时或设计时不会导致属性未找到错误?即有没有办法让Delphi以静默方式删除组件属性?

All*_*uer 20

是.只需删除该属性,然后覆盖DefineProperties并在那里处理它.这将通过加载您可以丢弃的值来满足流式传输系统.写入流时一定不要做任何事情.


Zoë*_*son 19

根据属性,最简单的方法是离开属性,但将其标记为已弃用,只是将读/写位指向一个从未使用过的字段.

或者,你可以重写DefineProperties,并调用Filer.DefineProperty('PropertyName', ReadProc);其中属性名是已删除了财产,ReadProc是调用各种行者阅读*函数的函数.这样做的好处是属性不再在您的界面中.

例如,假设您已删除此属性:

property Center: TPoint read FPoint write SetPoint;
Run Code Online (Sandbox Code Playgroud)

以下是您要添加到组件的内容:

TMyComponent = class...
private
  procedure SkipReadPoint(Reader: TReader);
protected
  procedure DefineProperties(Filer: TFiler); override;
end;

procedure TMyComponent.DefineProperties(Filer: TFiler);
begin
  inherited;
  Filer.DefineProperty('Center', SkipReadPoint, nil, False);
end;

procedure TMyComponent.SkipReadPoint(Reader: TReader);
begin
  Reader.ReadListBegin;
  Reader.ReadInteger;
  Reader.ReadInteger;
  Reader.ReadListEnd;
end;
Run Code Online (Sandbox Code Playgroud)

跳过布尔或整数这样的简单类型更容易,因为您只需调用ReadBooleanReadInteger不使用ReadList函数即可.

在我们的例子中,我们在一堆类中有很多类似的属性(对于CLX兼容性),所以我们有这样的全局"虚拟"函数:

procedure DummyReadBool(Self: Pointer; Reader: TReader);
begin
  Reader.ReadBoolean;
end;
const
  SkipReadBool: TMethod = (Code: @DummyReadBool; Data: nil);
Run Code Online (Sandbox Code Playgroud)

然后DefineProperty调用如下所示:

Filer.DefineProperty('PropName', TReaderProc(SkipReadBool), nil, False);
Run Code Online (Sandbox Code Playgroud)

这样每个类都不必具有重复的Skip*函数.

  • @Ken:我不明白你的反对意见.Amy特别要求在运行时加载DFM,并且在删除的属性上没有失败.显然这是向后兼容性要求,或者她刚刚打开表单并告诉它删除引用.我想我可以说"不",但这似乎并不十分有用. (5认同)

Ken*_*ite 6

如果它存储在.DFM中或在代码中引用,则无法"静默"删除它.

如果它没有在代码中引用,并且它存储在文本.DFM文件中,则JVCL有一个名为的实用程序DFM Cleaner,它将通过.DFM并为您删除属性.然后,您可以打开表单并安全地重新编译应用程序.它JVCL$(JVCL)\DevTools安装过程中的一部分并放在文件夹中.

  • JVCL DFM清洁器实用程序有一个非常酷的用途,我不能没有; 能够维护我在各种版本的Delphi中经常打开的源代码库,我需要删除更新版本的Delphi添加的东西,这些东西会破坏旧版本(ExplicitHeight,以及类似的东西,在Forms和Controls中). (3认同)