Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Сохранение свойств шрифтов

01.01.2007
//Saving and restoring font properties in the registry
Uses typInfo, Registry;
Function GetFontProp( anObj: TObject) : TFont;
Var
 
PInfo: PPropInfo;
Begin
 
{ try to get a pointer to the property information for a property with the
    name
'Font'. TObject.ClassInfo returns a pointer to the RTTI table,
which
    we need to
pass to GetPropInfo }
 
PInfo := GetPropInfo( anObj.ClassInfo, 'font' );
 
Result := Nil;
 
If PInfo <> Nil Then
   
{ found a property with this name, check if it has the correct type }
   
If (PInfo^.Proptype^.Kind = tkClass) and
       
GetTypeData(PInfo^.Proptype^)^.ClassType.InheritsFrom(TFont)
   
Then
     
Result := TFont(GetOrdProp( anObj, PInfo ));
End; { GetfontProp }
Function StyleToString( styles: TFontStyles ): String;
var
  style
: TFontStyle;
Begin
 
Result := '[';
 
For style := Low(style) To High(style) Do Begin
   
If style IN styles Then Begin
     
If Length(result) > 1 Then
        result
:= result + ',';
      result
:= result + GetEnumname( typeInfo(TFontStyle), Ord(style));
   
End; { If }
 
End; { For }
 
Result := Result + ']';
End; { StyleToString }
Function StringToStyle( S: String ): TFontStyles;
Var
  sl  
: TStringlist;
  style
: TfontStyle;
  i    
: Integer;
Begin
 
Result := [];
 
If Length(S) < 2 Then Exit;
 
If S[1] = '[' Then
   
Delete(S, 1, 1);
 
If S[Length(S)] = ']' Then
   
Delete(S, Length(S), 1);
 
If Length(S) = 0 Then Exit;
  sl
:= TStringlist.Create;
 
try
    sl
.commatext := S;
   
For i := 0 To sl.Count-1 Do Begin
     
try
        style
:= TFontStyle( GetEnumValue( Typeinfo(TFontStyle), sl[i] ));
       
Include( Result, style );
     
except
     
end;
   
End; { For }
 
finally
    sl
.free
 
end;
End; { StringToStyle }
Procedure SaveFontProperties( forControl: TControl;
                              toIni
: TRegInifile;
                             
const section: String );
Var
  font
: TFont;
  basename
: String;
Begin
 
Assert( Assigned( toIni ));
  font
:= GetFontProp( forControl );
 
If not Assigned( font ) Then Exit;
  basename
:= forControl.Name+'.Font.';
  toIni
.WriteInteger( Section, basename+'Charset', font.charset );
  toIni
.WriteString ( Section, basename+'Name', font.Name );
  toIni
.WriteInteger( Section, basename+'Size', font.size );
  toIni
.WriteString ( Section, basename+'Color',
                     
'$'+IntToHex(font.color,8));
  toIni
.WriteString ( Section, basename+'Style',
                     
StyleToString( font.Style ));
End; { SaveFontProperties }
Procedure RestoreFontProperties( forControl: TControl;
                             toIni
: TRegInifile;
                             
const section: String );
Var
  font
: TFont;
  basename
: String;
Begin
 
Assert( Assigned( toIni ));
  font
:= GetFontProp( forControl );
 
If not Assigned( font ) Then Exit;
  basename
:= forControl.Name+'.Font.';
  font
.Charset :=
    toIni
.ReadInteger( Section, basename+'Charset', font.charset );
  font
.Name :=
    toIni
.ReadString ( Section, basename+'Name', font.Name );
  font
.Size :=
    toIni
.ReadInteger( Section, basename+'Size', font.size );
  font
.Color := TColor( StrToInt(
    toIni
.ReadString ( Section, basename+'Color',
                     
'$'+IntToHex(font.color,8))
                     
));
  font
.Style := StringToStyle(
    toIni
.ReadString ( Section, basename+'Style',
                       
StyleToString( font.Style ))
                     
);
End; { RestoreFontProperties }

It is also possible to wrap a font into a small component and stream it:

type
 
TFontWrapper= class( TComponent )
 
private
   
FFont: TFont;
   
Constructor Create( aOwner: TComponent ); override;
   
Destructor Destroy; override;
   
Procedure SetFont( value: TFont );
  published
    property
Font: TFont read FFont write SetFont;
 
end;
{ TFontWrapper }
constructor TFontWrapper.Create(aOwner: TComponent);
begin
  inherited
;
 
FFont :=TFont.Create;
end;
destructor
TFontWrapper.Destroy;
begin
 
FFOnt.Free;
  inherited
;
end;
procedure
TFontWrapper.SetFont(value: TFont);
begin
 
FFont.Assign( value );
end;
procedure TForm1
.Button1Click(Sender: TObject);
var
  helper
: TFontWrapper;
begin
 
If not Assigned(ms) then
    ms
:= TMemoryStream.Create
 
Else
    ms
.Clear;
  helper
:= TFontWrapper.Create( nil );
 
try
    helper
.font := label1.font;
    ms
.WriteComponent( helper );
 
finally
    helper
.free;
 
end; { finally }
  label1
.font.size := label1.font.size + 2;
end;
procedure TForm1
.Button2Click(Sender: TObject);
var
  helper
: TFontWrapper;
begin
 
If not Assigned(ms) then Exit;
  ms
.Position := 0;
  helper
:= TFontWrapper.Create( nil );
 
try
    ms
.ReadComponent( helper );
    label1
.font := helper.font;
 
finally
    helper
.free;
 
end; { finally }
end;
©Drkb::01947

 


function FontToStr(font: TFont): string;
  procedure yes
(var str: string);
 
begin
 
    str
:= str + 'y';
 
end;
  procedure
no(var str: string);
 
begin
 
    str
:= str + 'n';
 
end;
begin
 
 
{кодируем все атрибуты TFont в строку}
 
Result := '';
 
Result := Result + IntToStr(font.Color) + '|';
 
Result := Result + IntToStr(font.Height) + '|';
 
Result := Result + font.Name + '|';
 
Result := Result + IntToStr(Ord(font.Pitch)) + '|';
 
Result := Result + IntToStr(font.PixelsPerInch) + '|';
 
Result := Result + IntToStr(font.size) + '|';
 
if fsBold in font.style then
    yes
(Result)
 
else
   
no(Result);
 
if fsItalic in font.style then
    yes
(Result)
 
else
   
no(Result);
 
if fsUnderline in font.style then
    yes
(Result)
 
else
   
no(Result);
 
if fsStrikeout in font.style then
    yes
(Result)
 
else
   
no(Result);
end;
 
procedure
StrToFont(str: string; font: TFont);
begin
 
 
if str = '' then
   
Exit;
  font
.Color := StrToInt(tok('|', str));
  font
.Height := StrToInt(tok('|', str));
  font
.Name := tok('|', str);
  font
.Pitch := TFontPitch(StrToInt(tok('|', str)));
  font
.PixelsPerInch := StrToInt(tok('|', str));
  font
.Size := StrToInt(tok('|', str));
  font
.Style := [];
 
if str[0] = 'y' then
    font
.Style := font.Style + [fsBold];
 
if str[1] = 'y' then
    font
.Style := font.Style + [fsItalic];
 
if str[2] = 'y' then
    font
.Style := font.Style + [fsUnderline];
 
if str[3] = 'y' then
    font
.Style := font.Style + [fsStrikeout];
end;
 
function tok(sep: string; var s: string): string;
 
 
function isoneof(c, s: string): Boolean;
 
var
    iTmp
: integer;
 
begin
   
Result := False;
   
for iTmp := 1 to Length(s) do
   
begin
     
if c = Copy(s, iTmp, 1) then
     
begin
       
Result := True;
       
Exit;
     
end;
   
end;
 
end;
var
 
  c
, t: string;
begin
 
 
if s = '' then
 
begin
   
Result := s;
   
Exit;
 
end;
  c
:= Copy(s, 1, 1);
 
while isoneof(c, sep) do
 
begin
    s
:= Copy(s, 2, Length(s) - 1);
    c
:= Copy(s, 1, 1);
 
end;
  t
:= '';
 
while (not isoneof(c, sep)) and (s <> '') do
 
begin
    t
:= t + c;
    s
:= Copy(s, 2, length(s) - 1);
    c
:= Copy(s, 1, 1);
 
end;
 
Result := t;
end;

Взято с https://delphiworld.narod.ru


Нужно сохранять атрибуты шрифта (имя, размер и т.п.) а не сам обьект TFont. После считывания этой информации следует проверить существует ли такой шрифт, прежде чем его использовать. Чтобы не показаться голословным дополню ответ Borland'а своим примером сохранения/чтения шрифта в/из реестра

uses...Registry;
 
procedure
SaveFontToRegistry(Font: TFont; SubKey: string);
var
  R
: TRegistry;
 
FontStyleInt: byte;
  FS
: TFontStyles;
begin
  R
:= TRegistry.Create;
 
try
    FS
:= Font.Style;
   
Move(FS, FontStyleInt, 1);
    R
.OpenKey(SubKey, True);
    R
.WriteString('Font Name', Font.Name);
    R
.WriteInteger('Color', Font.Color);
    R
.WriteInteger('CharSet', Font.Charset);
    R
.WriteInteger('Size', Font.Size);
    R
.WriteInteger('Style', FontStyleInt);
 
finally
    R
.Free;
 
end;
end;
 
function ReadFontFromRegistry(Font: TFont; SubKey: string): boolean;
var
  R
: TRegistry;
 
FontStyleInt: byte;
  FS
: TFontStyles;
begin
  R
:= TRegistry.Create;
 
try
    result
:= R.OpenKey(SubKey, false); if not result then exit;
   
Font.Name := R.ReadString('Font Name');
   
Font.Color := R.ReadInteger('Color');
   
Font.Charset := R.ReadInteger('CharSet');
   
Font.Size := R.ReadInteger('Size');
   
FontStyleInt := R.ReadInteger('Style');
   
Move(FontStyleInt, FS, 1);
   
Font.Style := FS;
 
finally
    R
.Free;
 
end;
end;
 
procedure TForm1
.Button1Click(Sender: TObject);
begin
 
if FontDialog1.Execute then
   
begin
     
SaveFontToRegistry(FontDialog1.Font, 'Delphi Kingdom\Fonts');
   
end;
end;
 
procedure TForm1
.Button2Click(Sender: TObject);
var
 
NFont: TFont;
begin
 
NFont := TFont.Create;
 
if ReadFontFromRegistry(NFont, 'Delphi Kingdom\Fonts') then
   
begin //здесь добавить проверку - существует ли шрифт
      Label1
.Font.Assign(NFont);
     
NFont.Free;
   
end;
end;