概述
我正在编写自己的列表框控件,该控件源自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
下显示我自己的列表框项目类型。
感谢。
答案 0 :(得分:4)
有两种可能性:
1)使用TCollection
代替TList
,您的项目类应该是TCollectionItem
的后代。例如,panels
中TStatusBar
属性的实现方式。如果您的项目可以由同一个类组成,并且它们可以是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中的面板,非常方便。但在这种情况下,你不能拥有'项目'对象检查器中的属性,而不是你必须在设计时在弹出菜单中实现自己的按钮,例如'项目编辑器'或者'新项目'等等
如果项目可以自己绘制,具有不同类型并且可能有自己的孩子,则此实现非常有用。