Most VCL controls has Fonts
and ParentFont
property. It is a good practice to set ParentFont = True
and the Fonts will follow it\'s paren
One of possible ways would be to inject post-parentfont handling
just check procedure TControl.CMParentFontChanged
in VCL.Controls
unit
You should also make some uniform way of injecting font customizations to your controls. Maybe subclassing their WindowsProc or extending standard controls with interfaces like EX-controls in JediVCL
The backbone - the proof of concept that can hardly be replicated a lot as is - maintenance problems - is below.
unit xxx;
interface uses yyyy;
type
(*********** hijack start! ****)
TFontOverrideEvent = reference to procedure (const Sender: TObject; const Font: TFont);
TButton = class( VCL.StdCtrls.TButton )
protected
procedure ParentFontChanged(var m: TMessage); message CM_ParentFontChanged;
public
var FontOverrideEnabled: Boolean;
var OnFontOverride: TFontOverrideEvent;
end;
(**** hijack end! standard form declaration below ****)
TForm1 = class(TForm)
....
Button1: TButton;
...
procedure FormCreate(Sender: TObject);
...
implementation
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.OnFontOverride :=
procedure (const Sender: TObject; const LFont: TFont) begin
with LFont do Style := [fsBold] + Style;
end;
Button1.FontOverrideEnabled := true;
Button1.ParentFont := true;
PostMessage( Button1.Handle, CM_ParentFontChanged, 0, 0);
// trigger control to borrow font with customization
end;
....
(*** hijack implementation ***)
procedure TButton.ParentFontChanged(var m: TMessage);
var SilenceHim1: IChangeNotifier; SilenceHim2: TNotifyEvent;
begin
inherited;
// let VCL make standard font copying
// warning! it may also make AutoSize or other automatic re-layout!
// as we hide the fact of our font tuning from VCL - it would not
// have a chance to react to our customizations!
if FontOverrideEnabled and Assigned( OnFontOverride ) then
begin
SilenceHim2 := Font.OnChange;
SilenceHim1 := Font.FontAdapter;
try
Font.OnChange := nil;
Font.FontAdapter := nil;
OnFontOverride( Self, Font );
finally
Font.OnChange := SilenceHim2;
Font.FontAdapter := SilenceHim1;
end;
end;
end;
Then try in runtime to change From1.Font and see how Button1
applies the changes to itself
I think that the simplest way to achieve your goals is to set no font properties at design time. Use ParentFont = True
everywhere.
Then at runtime make whatever modifications you need to make. That allows you to change the font face centrally, and still have the rest of your program pick it up.
That is known VCL limitation.
You can either have ParentFont
or your custom font settings in which case changing font properties in parent will not be propagated.
The best way around that is to use ParentFont = true
everywhere and set custom font properties of specific controls at runtime in form's OnCreate
event. Of course, in that case you lose What You See Is What You Get
at design time, but you get more control over actual runtime appearance of your forms.
procedure TForm1.OnCreate(Sender: TObject);
begin
inherited;
Label1.Font.Style := [fsBold];
Label1.Font.Color := clRed;
end;
For applying user custom font selection, you would also need to recreate forms, or use ParentFont := true
before applying custom styles for specific controls, so they pick up your new font settings.