Delphi组件属性类,取决于组件';s所有者类

Delphi组件属性类,取决于组件';s所有者类,delphi,vcl,design-time,Delphi,Vcl,Design Time,我正在使用RAD Studio XE5构建我的应用程序 我发现尝试在TForm上发布属性是不太实际的。然后它必须作为一个包进行注册和安装,这对于大规模开发是不现实的 因此,我决定创建一个非可视组件(TFormPropertiesEditor),用于填充表单属性。使我的表格标准化的一种方法 该组件将被丢弃在基本表单上,其他表单都继承该表单(我们称之为TBaseForm)。因此,组件只会在“基本”表单上删除一次,然后通过继承,其他表单也会删除它 创建的组件将检测其所有者(BaseForm或其子代)的

我正在使用RAD Studio XE5构建我的应用程序

我发现尝试在TForm上发布属性是不太实际的。然后它必须作为一个包进行注册和安装,这对于大规模开发是不现实的

因此,我决定创建一个非可视组件(TFormPropertiesEditor),用于填充表单属性。使我的表格标准化的一种方法

该组件将被丢弃在基本表单上,其他表单都继承该表单(我们称之为TBaseForm)。因此,组件只会在“基本”表单上删除一次,然后通过继承,其他表单也会删除它

创建的组件将检测其所有者(BaseForm或其子代)的类,并创建可通过“Properties”属性访问的对象,该属性的类将以所有者类为条件

这样,在检查TBaseForm上的组件时,我只能访问TBaseFormProperties。在检查TSecondForm上的组件时,我还可以访问TSecondFormProperties。仅此而已,组件将具有足够的智能,能够检测出它应该作为属性属性公开的PropertyClass

组件将通过GetPropertiesClass检查表单,定义为:

function TBaseForm.GetPropertiesClass : TPropertiesClass;
begin
  Result := TBaseFormProperties;
end;

function TSecondForm.GetPropertiesClass : TPropertiesClass;
begin
  Result := TSecondFormProperties;
end;
每个表单都有一个对应的TProperties子代,如下所示:

TBaseForm ------------ TSecondForm ------------- ...
    |
TBaseFormProperties -- TSecondFormProperties --- ...
例如:

如果放置构件的表单是TBaseForm,则FProperty将是TBaseFormProperties。如果表单是TSecondForm,则Fproperty将是TSecondFormProperties。当然,TSecondFormProperties将继承TBaseFormProperties

但是,当我将组件放在表单上时,它似乎无法检测该组件属于哪个类

function TFormPropertiesEditor.GetPropertiesClass: TFormPropertiesClass;
begin
  Result :=  TBaseForm(Owner).GetPropertiesClass;  
end;
看起来TBaseForm(所有者)部分导致了问题。解释器卡在TBaseFrm上,而不考虑所有者是TTIALFILE还是TDEDFREST类型。 接口

因此,为了绕过TBaseForm(Owner)类型转换,我决定使用一个接口。因此,如果我使用声明GetPropertiesClass的接口:

IMasterForm = interface(IInterface)
  ['{B6122F34-65C4-4701-8A5E-50C8DABF5516}']
  function GetPropertiesClass : TFormPropertiesClass;
  end;


type
  TBaseForm = class(TForm, IMasterForm)
    MyFormPropertiesEditor1: TMyFormPropertiesEditor;
  private
    { Déclarations privées }
  public
    function GetPropertiesClass : UCommon.TFormPropertiesClass;
  end;     
以下是:

function TFormPropertiesEditor.GetPropertiesClass : TFormPropertiesClass;
begin
  Result := (Owner as IMasterForm).GetPropertiesClass;
end;
将结果输入到不支持的界面中错误

抽象祖先方法

然后,我决定添加一个额外的祖先层。我添加了一个类TMasterForm,TBaseForm从中继承。此TMasterForm将GetPropertiesClass声明为抽象和虚拟:

TMasterForm = class(TForm, IMasterForm)
    public
      function GetPropertiesClass : TFormPropertiesClass; virtual; abstract;
  end;


type
  TBaseForm = class(TMasterForm)
  private
    { Déclarations privées }
  public
    function GetPropertiesClass : UCommon.TFormPropertiesClass; override;
  end;
但是,我得到了一个AV,因为我认为IDE试图访问TMasterClass.GetPropertiesClass,这当然没有实现

如何完成这种类型转换?你知道我该怎么做吗

事先非常感谢


下载示例项目

代码中的问题是没有正确继承GetPropertiesClass方法

事实上,您没有在类族中继承它

在您的代码中,每个类类型都有其自己版本的GetPropertiesClass方法,因此,由于您将所有者类型转换为TBaseForm类,因此即使所有者是TSecondForm类,也会使用TBaseForm中的方法

所以您需要确保TBaseForm类中的GetPropertiesClass是虚拟的,并且TSecondForm中的merhod GetPropertiesClass被重写


这将确保即使当所有者为TSecondForm类时,将所有者类型转换为TBaseClass时,也会调用TSecondForm.GetProperties方法。

这里的基本问题是IDE不会在设计时实例化表单。因此,无论在form类中放入什么代码,它都不会由IDE执行。这是因为您没有向IDE注册表单


如果您希望IDE了解您的表单,那么您需要在IDE中注册它们。在这一点上,所有的代码都变得不必要了,因为你又回到了你试图避免的事情上。即在IDE中注册表单。你陷入了第22条军规的境地。如果您需要IDE了解表单,那么您需要注册它们。此时,您可以直接在对象检查器中显示属性。

您没有向IDE注册基本表单。因此,在设计时,您看到的表单不是
TBaseForm
类型。你所尝试的是行不通的。我认为你所有的工作都是徒劳的。回到绘图板上。也许你需要…@DavidHeffernan我不认为他走错了方向。某些组件的自定义属性编辑器没有使用类似的方法。@Silver我不知道IDE将如何实例化TBaseForm或任何派生类。它怎么知道要这么做呢?关于你的编辑,你看过我的评论了吗?IDE将如何执行您的代码?谢谢您的回答。我确实做到了。我甚至还添加了另一个类,TMasterForm=class(TForm),它具有GetPropertiesClass抽象和虚拟,TBaseForm从中继承。TBaseForm的GetPropertiesClass被声明为重写。但是,当我将组件放到表单上时,IDE现在尝试访问TMasterForm的GetPropertiesClass,这会导致AV,因为此方法是抽象的。