2012-07-02 13 views
5

Estoy actualizando algunas propiedades en un componente. Para evitar errores de propiedad faltantes, estoy usando DefineProperties para leer las propiedades antiguas de la transmisión. La mayoría de las propiedades funcionan bien, p. Entero, pero no puedo obtener propiedades basadas en TPersistent para trabajar. El procedimiento ReadProperty (TPersistent) en TReader está protegido, no es público y requiere un hack para acceder a él. Incluso entonces, nunca se llama al procedimiento ReadFontProperty y se produce la excepción de propiedad faltante.Utilice DefineProperties para reemplazar las propiedades de TPersistent, p. TFont

¿Cómo leo la propiedad TFont?

Aquí hay un código de muestra de cómo estoy tratando de hacerlo.

... 

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; 

... 

Actualización 1

Probamos la sugerencia de David usando el siguiente código:

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

...

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

Me aparece un error no válida Propiedad Valor. Supongo que tiene algo que ver con Charset del tipo TFontCharset (= System.UITypes.TFontCharset = 0..255). ¿Cómo leo este tipo de propiedad?

Respuesta

4

Para hacer esto, necesita trabajar con cada propiedad individual publicada de TFont y deberá usar nombres completamente calificados.

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, etc. ReadFontHeight debe leer los valores de las propiedades antiguas en el componente recién nombrado.

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

// etc. etc. 

actualización

le preguntas cómo leer la propiedad juego de caracteres. Esto es complejo porque puede escribirse como un identificador de texto (ver la constante FontCharsets en Graphics.pas), o como un valor entero simple. Aquí hay un código rápidamente pirateado que leerá su 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 ¿Cómo te hiciste con esto? Estoy bastante seguro de que es la respuesta a tu pregunta. –

+0

Hola David. Gracias por la respuesta. Estoy seguro de que es correcto, pero aún no he tenido la oportunidad de probarlo. Trataré de llegar pronto. – norgepaul

+0

Muy bien, solo me preguntaba si te encuentras con un problema y tienes curiosidad. –

Cuestiones relacionadas