代码之家  ›  专栏  ›  技术社区  ›  Mason Wheeler

如何发布整数列表?

  •  3
  • Mason Wheeler  · 技术社区  · 14 年前

    我想制作一个包含整数列表的组件作为它的序列化属性之一。我知道我不能申报 TList<integer> 作为一个 出版 属性,因为它不从tppersistent下降。我已经读到,如果重写define properties,您可以定义“假”发布的属性,但我不太确定这是如何工作的,尤其是在创建一个列表而不是单个值的假属性时。

    有人能给我指个方向吗?

    2 回复  |  直到 14 年前
        1
  •  5
  •   Ondrej Kelle    14 年前

    下面是一个关于 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
  •  1
  •   Cosmin Prund    14 年前

    最快、最简单的实现方法是使用一个tcollection——但是你要为用tcollectionitem类“修饰”每个整数付出代价!除非有很多整数,否则这是一种方法,因为您几乎可以免费获得对象检查器集成(就像在很少的额外工作时间内一样免费)。

    如果你想把你的列表保持在最新的高效表格(TLIST)中,那么你是对的,你要做的就是定义你自己的财产。查看graphics.pas单元,了解tpicture.defineproperties是如何实现的,因为这与您需要的非常接近!

    想法:如果您使用“defineproperties”路径,您可能希望查找registercomponenteditor,因为整数列表在对象检查器中不可见!