Delphi组件属性类取决于组件的Owner类

时间:2014-12-25 07:04:54

标签: delphi vcl design-time

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

我看到在TForm上尝试tu发布属性是不太实际的。然后它必须作为一个包注册和安装,然后它对于繁重的开发是不实际的。

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

组件将被删除在基本表单上,其他表单继承的形式(让我们称之为TBaseForm)。所以,组件只会在“基础”表单上删除一次,然后继承,其他每种形式都会有它。

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

这样,在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 --- ...

例如:

如果放置组件的Form是TBaseForm,则FProperties将是TBaseFormProperties。如果表单是TSecondForm,则FProperties将是TSecondFormProperties。当然,TSecondFormProperties将继承自TBaseFormProperties。

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

function TFormPropertiesEditor.GetPropertiesClass: TFormPropertiesClass;
begin
  Result :=  TBaseForm(Owner).GetPropertiesClass;  
end;

看起来TBaseForm(所有者)部分导致了问题。解释器停留在TBaseForm上,并且不会考虑所有者是否为TSecondForm或TThirdForm类型。

接口

因此,为了绕过TBaseForm(所有者)类型转换,我决定使用一个接口。所以如果我使用一个声明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声明为abstract和virtual:

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,当然没有实现。

如何完成此TypeCasting?我知道怎么办?

非常感谢您提前

下载示例项目 https://www.wetransfer.com/downloads/b524438609fc04257af803a8e3dd2eca20141225161239/764d108d335b9d296c3004dfea04a54620141225161240/9c8cc0

2 个答案:

答案 0 :(得分:2)

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

如果您希望IDE了解您的表单,则需要在IDE中注册它们。那时你的所有代码都变得不必要,因为你回到了你想要避免的事情上。即使用IDE注册表单。你陷入了Catch 22的境地。如果您需要IDE了解表单,则需要注册它们。此时,您也可以直接在Object Inspector中显示属性。

答案 1 :(得分:-1)

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

事实上,你并没有在班级家庭中继承它。

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

因此,您需要确保TBaseForm类中的GetPropertiesClass是虚拟的,并且TSecondForm中的merhod GetPropertiesClass被覆盖。

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