2010-05-21 54 views
3

我想製作一個包含整數列表作爲其序列化屬性之一的組件。我知道我不能聲明TList<integer>作爲已發佈的屬性,因爲它不會從TPersistent下降。我讀過你可以定義「假」發佈的屬性,如果你重寫DefineProperties,但我不太確定這是如何工作的,尤其是當涉及到創建一個列表的假屬性,而不是一個單一的值。如何發佈整數列表?

有人能指出我正確的方向嗎?

+0

什麼是整數的意思?如果它們與表單上的組件實例有某種相關性,那麼你可能會做類似TGridPanel一樣的操作。 ColumnSpan。 – 2010-05-21 06:49:53

回答

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 
+0

謝謝,這正是我所需要的。 – 2010-05-21 12:28:59

+0

+1優秀的解決方案@TOndrej – RRUZ 2010-05-22 00:37:34

1

實現它的最快最簡單的方法是使用TCollection - 但是您將花費每個Integer的「裝飾」TCollectionItem類的代價!除非有很多整數,否則這是要走的路,因爲您幾乎可以免費獲得Object Inspector集成(免費,因爲在額外的工作時間內)。

如果你確實想保持你的列表是當前高效的形式(TList),那麼你是對的,要走的路是定義你自己的屬性。查看Graphics.pas單元,瞭解如何實現TPicture.DefineProperties,因爲這與您需要的非常接近!

想法:如果你去「DefineProperties」路線,你可能想看看RegisterComponentEditor,因爲你的整數列表在Object Inspector中不可見!