2012-07-02 3 views
5

Sto aggiornando alcune proprietà in un componente. Per evitare errori di proprietà mancanti, sto utilizzando DefineProperties per leggere le vecchie proprietà dallo stream. La maggior parte delle proprietà funziona bene, ad es. Numero intero, ma non è possibile ottenere le proprietà basate su TPersistent per funzionare. La procedura ReadProperty (TPersistent) in Il dispositivo di lettura è protetto, non pubblico e richiede un trucco per accedervi. Anche in questo caso, la procedura ReadFontProperty non viene mai chiamata e si verifica l'eccezione di proprietà mancante.Utilizzare DefineProperties per sostituire le proprietà TPersistent, ad es. TFont

Come si legge la proprietà TFont?

Ecco un esempio di codice di come sto cercando di farlo.

... 

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

provato il suggerimento di David utilizzando il seguente codice:

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

...

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

ottengo un errore Valore proprietà Valido. Immagino che sia qualcosa a che fare con Charset di tipo TFontCharset (= System.UITypes.TFontCharset = 0..255). Come leggo questo tipo di proprietà?

risposta

4

Per fare questo è necessario lavorare con ogni singola proprietà pubblicata di TFont e sarà necessario utilizzare nomi completi.

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 ecc dovrebbe leggere i valori delle proprietà vecchi nel componente nuovo nome.

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

// etc. etc. 

Aggiornamento

vi chiedo come leggere la proprietà Charset. Questo è complesso perché può essere scritto sia come identificatore testuale (vedere la costante FontCharsets in Graphics.pas), sia come un valore intero semplice. Ecco un codice rapidamente hackerato che leggerà il tuo Charset.

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 Come è andato avanti con questo? Sono abbastanza sicuro che sia la risposta alla tua domanda. –

+0

Ciao David. Grazie per la risposta. Sono sicuro che sia corretto, ma non ho ancora avuto la possibilità di provarlo. Proverò ad arrivarci presto. – norgepaul

+0

OK bene, mi chiedevo solo se avessi incontrato un problema ed ero curioso. –