2010-05-21 3 views
3

Je veux faire un composant qui comprend une liste d'entiers comme l'une de ses propriétés sérialisés. Je sais que je ne peux pas déclarer un TList<integer> comme publié propriété, car elle ne descend pas de TPersistent. J'ai lu que vous pouvez définir les propriétés publiées « faux » si vous substituez DefineProperties, mais je ne suis pas tout à fait sûr de savoir comment cela fonctionne, surtout en ce qui concerne la création d'une propriété faux qui est une liste, pas une seule valeur.Comment publier une liste d'entiers?

Quelqu'un peut-il me diriger dans la bonne direction?

+0

Quelle est la signification des nombres entiers? Si elles sont en quelque sorte liées à des instances de composant sur le formulaire, vous pouvez faire quelque chose de similaire à un TGridPanel, par exemple. ColumnSpan. –

Répondre

5

Voici un exemple minimal avec DefineBinaryProperty (écrit en D2007, pas de génériques):

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; 

et .dfm ressemble à ceci:

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

Merci, c'est exactement ce dont j'avais besoin. –

+0

+1 excellente solution @TOndrej – RRUZ

1

La méthode la plus rapide et la plus simple pour y arriver est d'utiliser un TCollection - mais vous paierez le prix de "décorer" chaque entier avec une classe TCollectionItem! À moins qu'il y ait beaucoup d'entiers, c'est la solution, car l'intégration de l'inspecteur d'objets est presque gratuite (gratuitement comme dans les petites heures de travail supplémentaires).

Si vous voulez garder votre liste dans sa forme actuelle, très efficace (TList), alors vous avez raison, le chemin à parcourir est de définir votre propre propriété. Regardez dans l'unité Graphics.pas à la façon dont TPicture.DefineProperties est implémenté car c'est une correspondance très proche de ce dont vous avez besoin! Idée: Si vous allez sur la route "DefineProperties", vous pouvez regarder dans RegisterComponentEditor car votre liste Integer ne sera pas visible dans l'inspecteur d'objets!

Questions connexes