如何发布一个整数列表?

3
我希望制作一个组件,其中包含一个整数列表作为其序列化属性之一。我知道无法声明TList<integer>作为published属性,因为它不是从TPersistent继承而来的。我已经阅读了可以通过重写DefineProperties定义“虚假”发布属性,但是我不太确定如何操作,特别是在创建列表而不是单个值的虚假属性时。有人能指点我吗?

整数的含义是什么?如果它们与表单上的组件实例有关,您可以执行类似于TGridPanel使用ColumnSpan的操作。 - Uli Gerhardt
2个回答

5

以下是一个最简示例,使用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

1

最快、最简单的方法是使用TCollection - 但你需要为每个整数添加一个TCollectionItem类的“装饰”!除非有很多整数,否则这是一种可行的方式,因为你几乎可以免费获得对象检查器集成(免费意味着少花些额外的工作时间)。

如果你想保持列表的当前高效形式(TList),那么你需要定义自己的属性。看看Graphics.pas单元中如何实现TPicture.DefineProperties,因为那是与你所需非常接近的匹配!

想法:如果你选择“DefineProperties”路线,你可能需要查看RegisterComponentEditor,因为你的整数列表将不会在对象检查器中显示!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接