Delphi 编写属性编辑器-我需要一些指导

Delphi 编写属性编辑器-我需要一些指导,delphi,custom-controls,delphi-xe,Delphi,Custom Controls,Delphi Xe,概述 我正在创建一个从TCustomTreeView派生的组件,我想添加一个属性,该属性在对象检查器中显示一个下拉列表(paValueList?)。此列表必须基于附加到我的控件的另一个列表(TStrings)动态填充,例如,它可以是TComboBox、TListBox中的项目或TStringList中的字符串等 我有一些问题,但我真的可以做一些指导和建议 代码布局 我缩短了代码以使其更易于阅读,但布局基本上与我的相同 我已将我的组件包分为两个(相同的项目组),Package1包含组件代码(例如

概述

我正在创建一个从TCustomTreeView派生的组件,我想添加一个属性,该属性在对象检查器中显示一个下拉列表(paValueList?)。此列表必须基于附加到我的控件的另一个列表(TStrings)动态填充,例如,它可以是TComboBox、TListBox中的项目或TStringList中的字符串等

我有一些问题,但我真的可以做一些指导和建议


代码布局

我缩短了代码以使其更易于阅读,但布局基本上与我的相同

我已将我的组件包分为两个(相同的项目组),
Package1
包含组件代码(例如我的组件源自TCustomTreeView),而
Package2
包含注册过程和设计器单元(designide.dcp、DesignIntf、DesignEditors等)

Package2
是我认为需要添加属性编辑器的地方,该编辑器将用于从
Package1
中的TCustomTreeView派生的组件

包装1

unit MyTreeViewUnit;

implementation

uses
  ...
  Classes,
  SysUtils;

type
  TMyTreeView = class(TCustomTreeView)
  private
    FSomeList: TStringList; // property editor should be filled using this list
    procedure SetSomeList(const Value: TStringList);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property SomeList: TStringList read FSomeList write SetSomeList;
  end;

  ....
包装2

unit MyTreeViewPropUnit;

implementation

uses
  DesignIntf,
  DesignEditors,
  Classes;

type
  TMyTreeViewProperty = class(TStringProperty)
  public
    function GetAttributes: TPropertyAttributes; override;
    procedure GetValues(Proc: TGetStrProc); override;
    procedure Edit; override;
  end;

implementation

uses
  MyTreeViewUnit;  

function TMyTreeViewProperty.GetAttributes: TPropertyAttributes;
begin
  Result := [paValueList]; ?
end;

procedure TMyTreeViewProperty.GetValues(Proc: TGetStrProc);
begin
  inherited;
  // These cannot be added here!!
  // This list should be populated based on SomeList found in Package1 - MyTreeViewUnit.pas
  Proc('Item1');
  Proc('Item2');
end;

procedure TMyTreeViewProperty.Edit;
begin
  inherited;
  // ?
end;


问题

  • 第一个问题是我不知道我所做的是不是正确的方法,我的组件安装了,我可以毫无问题地使用它,尽管我的属性编辑器“测试”没有出现

  • 第二个问题是GetValues的填充方式。通过在线阅读一些文章,我基本了解了目前为止我在填充属性编辑器等方面所做的工作。这不能以这种方式添加,尽管出于我的需要,在本例中,我需要基于第一个单元中分配给SomeList的字符串填充GetValue(例如,正如我之前所说的,FSomeList可以是TListBox)

  • 这与问题2有关,我如何让我的属性编辑器(在工作时)与我的树视图通信,以便我可以相应地填充它

  • 如果有人能给我一些建议,或者更好地指导我阅读一篇关于撰写物业编辑的好文章/指南,我将不胜感激。我读过的一些东西,比如Delphi.about、DelphiDabbler等,对我来说不容易理解和理解(我很容易被问题弄糊涂和陷入困境)


    非常感谢

    这对于注释来说太长了,我想包含一些代码,所以这里有一个答案。首先,你的问题很广泛。你需要把事情搞清楚,这样你才能问到重点问题。事实上,我开始回答你的第二个问题,在我放弃之前很久,我写了一些不可读的东西

    您应该从不需要属性编辑器的代码开始,即正常的运行时代码。属性编辑器不能成为自定义控件开发的中心,因为属性编辑器仅在设计时用于加快速度。如果要持久化特性编辑器所做的更改,则这些更改将保存到“对象检查器”(Object Inspector)中以任何方式可见的已发布特性(*1),这些特性将依次保存到DFM文件中。在创建表单的运行时和重新打开表单的设计时(例如:如果关闭IDE并重新打开它),会还原相同的过程。由于所有内容都需要进入对象检查器,因此您可以跳过花哨的属性编辑器,使控件正常工作

    是什么促使我这么说的:

    procedure TMyTreeViewProperty.GetValues(Proc: TGetStrProc);
    begin
      inherited;
      // These cannot be added here!!
      // This list should be populated based on SomeList found in Package1 - MyTreeViewUnit.pas
      Proc('Item1');
      Proc('Item2');
    end;
    
    该评论告诉我,您还没有弄清楚如何将组件链接到其他组件!这实际上是一个微不足道的步骤,一旦你完成了这项工作,你就可以这样做:

    procedure TMyTreeViewProperty.GetValues(Proc: TGetStrProc);
    var s: string;
    begin
      if Assigned(FLinkedCombo) then
        for s in FLinkedCombo.Items do
          Proc(s); // Beware, written in Browser!
    end;
    
    即使是那些无关紧要的问题,如果没有这一部分,上述问题的答案也是不完整的,而这一部分包括关于
    TComponent.FreeNotification
    TComponent.RemoveFreeNotification
    TComponent.Notification
    的长谈

    一旦您的大部分工作正常,就可以开始使用您可能想要创建的任何属性编辑器。这项工作也将作为一个普通项目来完成:您的目标是创建一个简单的表单(例如
    tmycomponentseteditor
    ),可以编辑您的属性或组件。完成该工作后,您可以问:如何使此工作编辑器在设计时作为属性或组件编辑器可用


    *1) 当然,组件编辑器可以做涉及多个组件的奇特工作;它还可以使用其他方法保存内容(即:不依赖简单的已发布属性)。

    如果您有DevExpress垂直网格控件,您会发现它包含一个非常好的属性编辑器组件。我开始写我自己的一本,然后我发现我已经有了一个非常好的版本。您可以在此处找到更多信息:您已经为名为
    Test
    TMyTreeView
    字符串属性注册了属性编辑器,但是
    TMyTreeView
    在您发布的代码中没有属性
    Test
    。你希望属性编辑器准确地编辑什么?我注意到,也应该是
    'SomeList'
    而不是
    'Test'
    @KenWhite阅读我对Cosmin Prund的回答的评论,你会再次发现,像往常一样,我在一个问题上停留的时间太长,对我手头的任务更加困惑。我真的需要学会停止跳槽,而是坐下来,花时间了解信息和文档指南等。我似乎在说服自己,一切都会很容易做到,到那时,我已经太晚了,感到困惑和沮丧。我似乎不能保持清醒的头脑,看到并理解我一直在做的每件事,但我会继续努力!嗨,很抱歉回复晚了。我想在写这个问题的时候,我处于一种困惑的状态,所以我写的问题并不像我希望的那么清楚。在t之前,我需要花一些时间阅读更多关于属性编辑器的内容
    procedure TMyTreeViewProperty.GetValues(Proc: TGetStrProc);
    var s: string;
    begin
      if Assigned(FLinkedCombo) then
        for s in FLinkedCombo.Items do
          Proc(s); // Beware, written in Browser!
    end;