【问题标题】:How to publish a list of integers?如何发布整数列表?
【发布时间】:2011-02-22 05:00:06
【问题描述】:

我想制作一个包含整数列表作为其序列化属性之一的组件。我知道我不能将TList<integer> 声明为已发布 属性,因为它并非源自TPersistent。我已经读过,如果您覆盖 DefineProperties,您可以定义“假”发布的属性,但我不太确定它是如何工作的,特别是在创建一个列表而不是单个值的假属性时。

有人能指出正确的方向吗?

【问题讨论】:

  • 整数的含义是什么?如果它们以某种方式与表单上的组件实例相关,您可能会执行类似 TGridPanel 的操作,例如列跨度。

标签: delphi list properties


【解决方案1】:

这是DefineBinaryProperty 的最小示例(用 D2007 编写,没有泛型):

type
  TTestComponent = class(TComponent)
  private
    FList: TList;

    function GetValueCount: Integer;
    function GetValues(Index: Integer): Integer;
    procedure ReadValueList(Stream: TStream);
    procedure SetValues(Index: Integer; Value: Integer);
    procedure WriteValueList(Stream: TStream);
  protected
    procedure DefineProperties(Filer: TFiler); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    function AddValue(Value: Integer): Integer;
    procedure ClearValues;
    procedure DeleteValue(Index: Integer);

    property ValueCount: Integer read GetValueCount;
    property Values[Index: Integer]: Integer read GetValues write SetValues;
  end;

{ TTestComponent }

function TTestComponent.GetValueCount: Integer;
begin
  Result := FList.Count;
end;

function TTestComponent.GetValues(Index: Integer): Integer;
begin
  Result := Integer(FList[Index]);
end;

procedure TTestComponent.ReadValueList(Stream: TStream);
var
  Count, I, Value: Integer;
begin
  ClearValues;
  Stream.Read(Count, SizeOf(Count));
  for I := 0 to Count - 1 do
  begin
    Stream.Read(Value, SizeOf(Value));
    AddValue(Value);
  end;
end;

procedure TTestComponent.SetValues(Index: Integer; Value: Integer);
begin
  FList[Index] := Pointer(Value);
end;

procedure TTestComponent.WriteValueList(Stream: TStream);
var
  Count, I, Value: Integer;
begin
  Count := ValueCount;
  Stream.Write(Count, SizeOf(Count));
  for I := 0 to Count - 1 do
  begin
    Value := Values[I];
    Stream.Write(Value, SizeOf(Value));
  end;
end;

procedure TTestComponent.DefineProperties(Filer: TFiler);
begin
  inherited DefineProperties(Filer);
  Filer.DefineBinaryProperty('ValueList', ReadValueList, WriteValueList, ValueCount > 0);
end;

constructor TTestComponent.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FList := TList.Create;
  // add some values for testing
  AddValue(0);
  AddValue(1);
  AddValue(2);
end;

destructor TTestComponent.Destroy;
begin
  FList.Free;
  inherited Destroy;
end;

function TTestComponent.AddValue(Value: Integer): Integer;
begin
  Result := FList.Add(Pointer(Value));
end;

procedure TTestComponent.ClearValues;
begin
  FList.Clear;
end;

procedure TTestComponent.DeleteValue(Index: Integer);
begin
  FList.Delete(Index);
end;

.dfm 看起来像这样:

  object TestComponent1: TTestComponent
    Left = 96
    Top = 56
    ValueList = {03000000000000000100000002000000}
  end

【讨论】:

  • 谢谢,这正是我所需要的。
【解决方案2】:

实现它的最快、最简单的方法是使用 TCollection - 但您将付出使用 TCollectionItem 类“装饰”每个 Integer 的代价!除非有很多整数,否则这是要走的路,因为您几乎可以免费获得 Object Inspector 集成(免费,因为只需很少的额外工作时间)。

如果您确实希望将列表保持在当前的高效形式 (TList) 中,那么您是对的,要走的路就是定义您自己的属性。查看 Graphics.pas 单元,了解 TPicture.DefineProperties 是如何实现的,因为这与您的需求非常接近!

想法:如果您选择“DefineProperties”路线,您可能需要查看 RegisterComponentEditor,因为您的 Integer 列表将在 Object Inspector 中不可见!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-11
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多