2012-07-02 5 views
5

Ich aktualisiere einige Eigenschaften in einer Komponente. Um Fehler bei der Eigenschaft zu vermeiden, verwende ich DefineProperties, um die alten Eigenschaften aus dem Stream zu lesen. Die meisten Eigenschaften funktionieren gut, z.B. Integer, aber ich kann keine Eigenschaften basierend auf TPersistent zu arbeiten. Die ReadProperty (TPersistent) Prozedur in TReader ist geschützt, nicht öffentlich und erfordert einen Hack, um darauf zuzugreifen. Selbst dann wird die ReadFontProperty-Prozedur nie aufgerufen und die Ausnahme der fehlenden Eigenschaft tritt auf.Verwenden Sie DefineProperties, um TPersistent-Eigenschaften zu ersetzen, z. TFont

Wie lese ich die TFont Eigenschaft?

Hier ist ein Beispielcode, wie ich es versuche.

... 

type 
    TMyComponent = class(TComponent) 
    strict private 
    // Removed 
    //FIntegerProperty: Integer; 
    //FFontProperty: TFont; 

    // New 
    FNewIntegerProperty: Integer; 
    FNewFontProperty: TFont; 

    procedure ReadIntegerProperty(Reader: TReader); 
    procedure ReadFontProperty(Reader: TReader); 
    protected 
    procedure DefineProperties(Filer: TFiler); override; 
    published 
    // Removed properties 
    //property IntegerProperty: Integer read FIntegerProperty write FIntegerProperty; 
    //property FontProperty: TFont read FFontProperty write SetFontProperty; 

    // New properties 
    property NewIntegerProperty: Integer read FNewIntegerProperty write FNewIntegerProperty; 
    property NewFontProperty: TFont read FNewFontProperty write SetNewFontProperty; 
    end; 

implementation 

procedure TMyComponent.DefineProperties(Filer: TFiler); 
begin 
    inherited; 

    // This works 
    Filer.DefineProperty('IntegerProperty', ReadIntegerProperty, nil, FALSE); 

    // This doesn't 
    Filer.DefineProperty('FontProperty', ReadFontProperty, nil, FALSE); 
end; 

procedure TMyComponent.ReadIntegerProperty(Reader: TReader); 
begin 
    FNewIntegerProperty:= Reader.ReadInteger; 
end; 

type 
    THackReader = class(TReader); 

procedure TMyComponent.ReadFontProperty(Reader: TReader); 
begin 
    { TODO : This doesn't work. How do we read fonts? } 
    THackReader(Reader).ReadProperty(FNewFontProperty); 
end; 

... 

Update 1

David Vorschlag mit dem folgenden Code versucht:

Filer.DefineProperty('Font.CharSet', ReadFontCharSet, nil, False); 

...

procedure TMyComponent.ReadFontCharSet(Reader: TReader); 
begin 
    Reader.ReadInteger; 
end; 

Ich erhalte einen Ungültiger Eigenschaftswert Fehler. Ich nehme an, es ist etwas mit Charset vom Typ TFontCharset (= System.UITypes.TFontCharset = 0..255) zu tun. Wie lese ich diese Art von Eigentum?

Antwort

4

Um dies zu tun, müssen Sie mit jeder einzelnen veröffentlichten Eigenschaft von TFont arbeiten und Sie müssen voll qualifizierte Namen verwenden.

Filer.DefineProperty('FontProperty.Name', ReadFontName, nil, False); 
Filer.DefineProperty('FontProperty.Height', ReadFontHeight, nil, False); 
Filer.DefineProperty('FontProperty.Size', ReadFontSize, nil, False); 
// and so on for all the other published properties of TFont 

ReadFontName, ReadFontHeight usw. sollten die alten Eigenschaftswerte in die neu benannte Komponente lesen.

procedure TMyComponent.ReadFontName(Reader: TReader); 
begin 
    FNewFontProperty.Name := Reader.ReadString; 
end; 

// etc. etc. 

aktualisieren

Sie fragen, wie Sie die Eigenschaft Charset zu lesen. Dies ist komplex, da es entweder als Textbezeichner (siehe FontCharsets Konstante in Graphics.pas) oder als einfacher ganzzahliger Wert geschrieben werden kann. Hier ist ein kurzer gehackter Code, der deinen Charset lesen wird.

procedure TMyComponent.ReadFontCharset(Reader: TReader); 

    function ReadIdent: string; 
    var 
    L: Byte; 
    LResult: AnsiString; 
    begin 
    Reader.Read(L, SizeOf(Byte)); 
    SetString(LResult, PAnsiChar(nil), L); 
    Reader.Read(LResult[1], L); 
    Result := UTF8ToString(LResult); 
    end; 

    function ReadInt8: Shortint; 
    begin 
    Reader.Read(Result, SizeOf(Result)); 
    end; 

    function ReadInt16: Smallint; 
    begin 
    Reader.Read(Result, SizeOf(Result)); 
    end; 

var 
    Ident: string; 
    CharsetOrdinal: Integer; 

begin 
    Beep; 
    case Reader.ReadValue of 
    vaIdent: 
    begin 
     Ident := ReadIdent; 
     if not IdentToCharset(Ident, CharsetOrdinal) then begin 
     raise EReadError.Create('Could not read MyFont.Charset'); 
     end; 
     FNewFontProperty.Charset := CharsetOrdinal; 
    end; 
    vaInt8: 
    FNewFontProperty.Charset := ReadInt8; 
    vaInt16: 
    FNewFontProperty.Charset := ReadInt16; 
    else 
    raise EReadError.Create('Could not read FontProperty.Charset'); 
    end; 
end; 
+0

@norgepaul Wie bist du damit klargekommen? Ich bin mir ziemlich sicher, dass es die Antwort auf deine Frage ist. –

+0

Hallo David. Danke für die Antwort. Ich bin mir sicher, dass es korrekt ist, aber ich hatte noch keine Gelegenheit es zu testen. Ich werde versuchen, bald darauf zu kommen. – norgepaul

+0

OK gut, ich habe mich nur gefragt, ob du auf ein Problem gestoßen bist und neugierig warst. –

Verwandte Themen