I'm updating some properties in a component. In order to avoid missing property errors I'm using DefineProperties to read the old properties from the stream. Most properties work fine e.g. Integer, but I can't get properties based on TPersistent to work. The ReadProperty(TPersistent) procedure in TReader is protected, not public and requires a hack to access it. Even then, the ReadFontProperty procedure is never called and the missing property exception occurs.
How do I read the TFont property?
Here's some sample code of how I'm trying to do it.
...
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
Tried David's suggestion using the following code:
Filer.DefineProperty('Font.CharSet', ReadFontCharSet, nil, False);
...
procedure TMyComponent.ReadFontCharSet(Reader: TReader);
begin
Reader.ReadInteger;
end;
I get an Invalid Property Value error. I guess it's something to do with Charset being of type TFontCharset (= System.UITypes.TFontCharset = 0..255). How do I read this type of property?
In order to do this you need to work with each individual published property of TFont
and you will need to use fully qualified names.
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
etc. should read the old property values into the newly named component.
procedure TMyComponent.ReadFontName(Reader: TReader);
begin
FNewFontProperty.Name := Reader.ReadString;
end;
// etc. etc.
Update
You ask how to read the Charset property. This is complex because it can be written either as a textual identifier (see the FontCharsets
constant in Graphics.pas), or as a plain integer value. Here is some rapidly hacked together code that will read your 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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With