Reputation:
Is there a quick and effective way of applying a global Font to be used in a project?
By this I mean I would like to set a specific Font name that all controls in my project will use such as TButton
, TEdit
, TLabel
etc.
Typically setting the Font for the Form rather than a specific control will change all the controls on that Form to the Font specified.
There is a slight issue with this however, if you have manually changed a Font on a specific control, then setting the Font by the Form will no longer update those controls that have previously been changed manually.
Idea 1
I was thinking of using a For loop and iterating through each component on my Forms and setting the Font this way, such as:
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
with TForm(Self) do
begin
for i := 0 to ComponentCount - 1 do
begin
if Components[i] is TButton then
begin
TButton(Components[i]).Font.Name := 'MS Sans Serif';
TButton(Components[i]).Font.Size := 8;
TButton(Components[i]).Font.Style := [fsBold];
end;
if Components[i] is TLabel then
begin
TLabel(Components[i]).Font.Name := 'MS Sans Serif';
TLabel(Components[i]).Font.Size := 8;
TLabel(Components[i]).Font.Style := [fsBold];
end;
end;
end;
end;
But doing this seems very messy, it will also be a considerable amount of code for a simple task.
Idea 2
I know I could manually change the fonts at design time one by one for each control, but with several forms to go through this could take time and even then I might of missed a control.
Idea 3
Similar to Idea 2, another way could be to view the Form as Text (DFM) and Find and Replace the font that way.
Basically I am going for consistency within my Application, and having one Font used throughout is what I was looking to achieve.
Am I missing something completely obvious here, is what I am trying to do overkill for such a task?
Upvotes: 24
Views: 8943
Reputation: 642
The real key, as was mentioned, is to ensure that all your forms descend from your own application base form.
Then, you can view each form and button etc, and review the properties, where any modified font property should be displayed in bold, and is easily identified. Most properties have a "Revert to inherited" menu choice. This should essentially undo any previous selection, without having to go to the text version for editting. (Although it probably does exactly that, deleting any text entry resulting from previous font-setting).
I would definitely want to fix each form once rather than leaving it defined incorrectly and adding more code to fix it at runtime. That change will leave you with a worse problem if you later decide to do something different.
Upvotes: 2
Reputation: 711
If you want to do this runtime, like you describe it in Idea 1, you should consider making it a recursive function, like this:
procedure SetFontProperties(Control: TControl; Name: TFontName; Size: Integer; Styles: TFontStyles);
// Set font properties
var
Index: Integer;
Font: TFont;
AnObject: TObject;
ChildControl: TControl;
begin
// Set font properties
AnObject := GetObjectProp(Control, 'Font', nil);
if AnObject is TFont then
begin
// Set properties
Font := TFont(AnObject);
Font.Name := Name;
Font.Size := Size;
Font.Style := Styles;
end;
// Set child font properties
if Control is TWinControl then
begin
// Set
for Index := 0 to TWinControl(Control).ControlCount - 1 do
begin
// Child control
ChildControl := TWinControl(Control).Controls[Index];
// Set font properties
SetFontProperties(ChildControl, Name, Size, Styles);
end;
end;
end;
You can then switch fonts for all controls within a form by using it like this:
SetFontProperties(Self, 'Courier', 14, []);
The function will then set the font properties of the form, and the font properties of all child controls on the form, including controls nested within TPanels or other container controls.
However I do agree with you that it's sort of a half messy way of doing it.
Upvotes: 1
Reputation: 613382
As discussed in the comments, the key to this is the ParentFont
property. This property is defined at various points in the VCL hierarchy. If you set ParentFont
to be True
for all components in the chain, then you can change the fonts for the entire application simply by modifying
Application.DefaultFont
By default most components set ParentFont
to True
and so you have nothing to do. The odd one out though is TForm
. A brand new default form has ParentFont
set to False
. This is somewhat disappointing but I suspect reflects the fact that the original designers of the VCL did not anticipate this and that ParentFont
was grafted on relatively late in the development of the VCL.
No matter, in an ideal world, all forms in your application should be derived from a common base class that you control. If that is so then you can simply make the change there, set ParentFont
to be True
, make sure no explicit font settings are applied to any components on you forms, and you are golden. Control the entire application's fonts through a single property. If you don't have a common base class for your forms, here's an ideal time to add it. If you don't want to do that then you need to set ParentFont
for each form.
Other related properties are Screen.MessageFont
and Screen.MenuFont
. These provide global control over the fonts used in message boxes and menus. However, recent versions of Delphi have handed back to Windows control over the painting of message boxes and menus and so these properties have no effect.
Upvotes: 27