Delphi 如何使自定义控件的TList属性可流化?
概述 我正在编写从TCustomListBox派生的自己的listbox控件 我还开始实现自己的属性编辑器,以允许在设计时编辑项目的标题和imageindex。我正在自定义绘制列表框,并已从控件发布了自己的ImageList属性 问题 到目前为止,一切正常,但我无法将项目流式传输到dfm。我相信这可能是因为标准listbox Items属性是TStrings,并且从我的控件中发布了我自己的属性,该属性也是命名的Items,但属于TList类。我不希望显示listbox的standard Items属性,而是希望显示我自己的Items类型 因此,即使我可以在设计时将控件放到表单上,使用我自己的属性编辑器编辑项,如果我运行应用程序,列表框为空,如果我在设计时查看DFM,然后返回表单视图,这些项也会消失,基本上它们没有存储在DFM中,我不确定如何更正 代码的相关摘录类似于为解决此问题而添加的注释: 我自己的列表框项目类型:Delphi 如何使自定义控件的TList属性可流化?,delphi,Delphi,概述 我正在编写从TCustomListBox派生的自己的listbox控件 我还开始实现自己的属性编辑器,以允许在设计时编辑项目的标题和imageindex。我正在自定义绘制列表框,并已从控件发布了自己的ImageList属性 问题 到目前为止,一切正常,但我无法将项目流式传输到dfm。我相信这可能是因为标准listbox Items属性是TStrings,并且从我的控件中发布了我自己的属性,该属性也是命名的Items,但属于TList类。我不希望显示listbox的standard Item
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;
这是控件最简单的形式。我想对控件所做的一切,如自定义图形和“我的项目”属性的属性编辑器等,都是按照我的意愿进行的
问题:
我需要做些什么才能使FItems财产流向DFM?DFM应在项目下显示我自己的每个列表框项目类型
谢谢。有两种可能: 1使用TCollection而不是TList,并且您的项类应该是TCollectionItem的后代。例如,这就是如何在TStatusBar中实现panels属性。如果您的项可以由相同的类组成,并且它们可以是TCollectionItem的后代(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就足够了。在TTabControl、TPageControl、TMainMenu和其他组件中就是这样做的。在这种情况下,项可能也包含它们自己的项,所有这些结构都显示在IDE的“结构”面板中,这非常方便。但在这种情况下,在对象检查器中不能有“Items”属性,而是必须在设计时在弹出菜单中实现自己的按钮,如“Items editor”或“New item”等。
如果项目可以“自行绘制”,具有不同的类型,并且可能有自己的子项,则此实现非常有用。t收集是srteamable,TList不是,以及您未指定的项目类型。我现在可以按照选项1使用TCollection,而不是TList。非常感谢您的解释和详细的回答。还有第三种选择。让主组件重写virtual DefineProperties方法,为TList数据提供自定义流。请看。@RemyLebeau很有趣,看起来很复杂,我相信这将是一本有趣的读物:谢谢您添加了另一个选项。