1

我是 Delphi 组件开发的新手,因此想知道,是否有可能实现我的任务。

我需要创建一个基于 TScrollBox 的可视组件(用户控件),它将代表一堆 TPanel,所有这些面板都将在该 TScrollBox 内对齐为“顶部”,并且可以具有不同的高度。它必须充当 TCollection(添加、删除、重新排序),并且必须允许用户在设计时将其他控件添加到这些面板中。

我为组件创建了这些类:

type
  TPanelsGrid = class;

  TPanelsGridItem = class(TCollectionItem)
  private
    FPanel: TPanel;
    procedure SetPanel(Value: TPanel);
    function GetGrid: TPanelsGrid;
  protected
    function GetDisplayName: string; override;
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    // This is my TPanel object that should be used at designtime
    // I thought "stored True" will serialize it automatically but I was wrong
    property Panel: TPanel read FPanel write SetPanel stored True; 
  end;

  TPanelsGridItems = class(TCollection)
  private
    FPanelsGrid: TPanelsGrid;
  protected
    function GetItem(Index: Integer): TPanelsGridItem;
    procedure SetItem(Index: Integer; Value: TPanelsGridItem);

    function GetOwner: TPersistent; override;
    procedure Update(Item: TCollectionItem); override;
  public
    property EditorsGrid: TPanelsGrid read FPanelsGrid;
    property Items[Index: Integer]: TPanelsGridItem
      read GetItem write SetItem; default;

    constructor Create(PanelsGrid: TPanelsGrid);
    function Add: TPanelsGridItem;
    procedure Delete(Index: Integer);
  end;

  TPanelsGrid = class(TScrollBox)
  private
    FItems: TPanelsGridItems;
    procedure SetItems(Value: TPanelsGridItems);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Items: TPanelsGridItems read FItems write SetItems;
  end;

该组件在设计时工作正常,我可以在堆栈中添加-删除面板,当我在任何面板上放置一些控件(例如 TCheckbox)时,它显示为“由该面板拥有”:例如我无法拖动此复选框面板外。

但此复选框不存储在 DFM 文件中,也不显示在“结构”窗口中。

我想TPanel的内容必须有一些手动序列化-反序列化,但我不知道该怎么做。在 Internet 上找不到任何示例。请给我一些指导,如果这样的实施是可能的。

加法

这是在网格中添加 3 个面板后我的 DFM 文件片段的样子:

  object PanelsGrid1 : TPanelsGrid 
    Left = 8
    Top = 8
    Width = 536
    Height = 382
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 0
    Items = <
      item
      end
      item
      end
      item
      end>
  end

如您所见,所有项目都是空的,但我将一个复选框和单选按钮放入项目#3。

4

3 回答 3

1

毕竟我决定放弃使用 TCollection,因为在测试 DefineProperties 方法期间,我遇到了一致的 IDE 崩溃。我认为 TCollection 并不是为这样的任务而设计的。

我在控件 ExtCtrls.TCustomCategoryPanelGroup 内的 Delphi 源代码中创建了一个适当的实现。它维护可以在设计时和运行时添加或删除的面板堆栈。我使用 TCustomCategoryPanelGroup 和 TCustomCategoryPanel 的源代码创建了自己的类,它可以按我的意愿工作。

于 2010-09-30T14:51:58.393 回答
0

我想你可以看看TMS Poly List 控件

TMS Advanced Poly List 组件提供了极其通用和灵活的架构,可以在用户界面中创建几乎任何可能的项目列表。这通常在但不限于新的 Office 2010 应用程序菜单中看到。与大多数用户界面列表控件(其中列表由相同类型的项目或相同类型的项目的集合组成)相反,TMS 高级多边形列表组件可以包含多态项目。所有项目只需要从基类 TCustomItem 继承,并且可以添加任何继承的项目。TMS Advanced Poly List 组件带有大量预构建的列表项,但可以通过 TCustomItem 基类的降序或已提供的任何类来添加自定义项类。有项目类显示为列表部分项目,具有 HTML 格式的文本项目、具有按钮的文本项目、具有展开/折叠行为的项目、具有图像的项目等等。可以在设计时使用丰富的设计时编辑器和在运行时通过代码将项目添加到多态列表中。

于 2010-09-27T16:37:45.540 回答
0

确保您的子面板有名称。您可以覆盖 TCollection.Notify,如果 Action 是 cnAdded,请确保面板具有名称。

于 2010-09-28T08:35:23.977 回答