如何从我的自定义控件流式传输中创建TList属性?

时间:2016-05-28 14:57:24

标签: delphi

概述

我正在编写自己的列表框控件,该控件源自TCustomListBox

我也开始实现自己的属性编辑器,允许在设计时编辑项目的标题和图像索引(我自定义绘制列表框并从我的控件中发布了我自己的ImageList属性)。

问题

到目前为止,一切都运行良好,但是我无法将项目传输到dfm。我相信这可能是因为标准列表框Items属性属于TStrings,并且从我的控件中我发布了自己的属性,该属性也被命名为Items,但是TList课程。我不希望列表框的标准Items属性显示,而是我自己的Items类型。

即使我可以在设计时将控件放到表单上,使用我自己的属性编辑器编辑Items,如果我运行应用程序,列表框为空,如果我在设计时查看DFM然后返回回到表单视图的项目也没了,基本上它们没有存储在DFM中,我不确定如何纠正这个?

代码的相关摘录如下所示(为此问题添加了评论):

我自己的列表框项目类型:

TListBoxItem = class(TObject) // Also tried TPersistent
private
  FCaption: string;
  FImageIndex: Integer;
public // Also tried Published
  property Caption: string read FCaption write FCaption;
  property ImageIndex: Integer read FImageIndex write FImageIndex;
end;

自定义控件:

TMyListBox = class(TCustomListBox)
private
  FImageList: TImageList;
  FItems: TList;
  procedure SetImageList(const Value: TImageList);
protected
  procedure Notification(AComponent: TComponent;
    Operation: TOperation); override;
  procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); Override;
  procedure MeasureItem(Index: Integer; var Height: Integer); override;
public
  constructor Create(AOwner: TComponent); override;
  destructor Destroy; override;

  procedure AddItem(ACaption: string; AImageIndex: Integer); // adds a new item to FItems and the listbox control
published
  .....
  property Color;
  property Images: TImageList read FImageList write SetImageList;
  property Items: TList read FItems write FItems; // take over standard Items type and publish my own Items type instead
  .....
  property Sorted;
  property TabOrder;
  property TabStop;
  property Visible;
  property OnClick;
  property OnContextPopup;
  property OnDblClick;
  property OnDragDrop;
  property OnDragOver;
  //property OnDrawItem;
  property OnEndDock;
  property OnEndDrag;
  property OnEnter;
  property OnExit;
  property OnKeyDown;
  property OnKeyPress;
  property OnKeyUp;
  //property OnMeasureItem;
  property OnMouseDown;
  property OnMouseEnter;
  property OnMouseLeave;
  property OnMouseMove;
  property OnMouseUp;
  .....
end;

这是最简单形式的控件。我想用控件做的一切,比如我Items属性的自定义绘图和属性编辑器等,都是我想要的。

问题

为了使FItems属性可以流式传输到DFM,我需要做些什么? DFM应在Items下显示我自己的列表框项目类型。

感谢。

1 个答案:

答案 0 :(得分:4)

有两种可能性:

1)使用TCollection代替TList,您的项目类应该是TCollectionItem的后代。例如,panelsTStatusBar属性的实现方式。如果您的项目可以由同一个类组成,并且它们可以是TCollectionItem的后代本身是TPersistent后代,则这种方式更可行。它看起来像是:

TMyListBoxItem = class (TCollectionItem)
private
  FCaption: string;
  FImageIndex: Integer;
published  //only published properties will be saved to dfm
  property Caption: string read FCaption write FCaption;
  property ImageIndex: Integer read FImageIndex write FImageIndex;
end;

TMyListBoxItemClass = class of TMyListBoxItem; //class reference, or metaclass, we need it to properly initialize TCollection

TMyListBox = class(TCustomListBox)
private
// imageList etc...
  FItems: TCollection;
public
  constructor Create(aOwner: TComponent); override;
  destructor Destroy; override;
  // other funcs
published
  property Items: TCollection read fItems write fItems;
  //other properties
end;

//implementation
constructor TMyListBox.Create(aOwner: TComponent)
begin
  inherited;
  //other initializations
  fItems:=TCollection.Create(TMyListBoxItemClass); //so TCollection is able to create items as many as needed
end;

destructor TMyListBox.destroy;
begin
 fItems.free;
 //other destruction
 inherited Destroy;
end;

主要是它。顺便说一句,当你需要流式传输到dfm时,永远不要从TObject下降,它从TPersistent开始(这正好意味着它能够被保存然后加载)并且在TComponent中完全实现了。

2)每个项目都是TControl后代,其自定义列表框作为其父级,表单作为其所有者(可能TComponent就足够了)。这是TTabControlTPageControlTMainMenu和其他组件的完成方式。在这种情况下,项目也可能包含自己的项目,所有这些结构都显示在'结构中。 IDE中的面板,非常方便。但在这种情况下,你不能拥有'项目'对象检查器中的属性,而不是你必须在设计时在弹出菜单中实现自己的按钮,例如'项目编辑器'或者'新项目'等等 如果项目可以自己绘制,具有不同类型并且可能有自己的孩子,则此实现非常有用。