Reputation: 188
I have an application that needs to be adaptive to a range of different screen sizes (resolutions). Most of that I've done using table layout panels.
But some of the control (buttons and labels mostly) have too large font and the text doesn't fit in the control. So far I've managed change the font of some controls by using
if (Screen.PrimaryScreen.Bounds.Width < 1440)
{
button_5.Font = new Font("Impact", button_5.Font.Size - 4);
}
But that is too much text to add for every single control in the application.
Is there a way of changing the fonts of all the controls on the application at once? Or at least all controls on a form?
Upvotes: 5
Views: 10578
Reputation: 27001
Based on Steve's good answer, I would do the following improvements:
/// <summary>
/// Changes fonts of controls contained in font collection recursively. <br/>
/// <b>Usage:</b> <c><br/>
/// SetAllControlsFont(this.Controls, 20); // This makes fonts 20% bigger. <br/>
/// SetAllControlsFont(this.Controls, -4, false); // This makes fonts smaller by 4.</c>
/// </summary>
/// <param name="ctrls">Control collection containing controls</param>
/// <param name="amount">Amount to change: posive value makes it bigger,
/// negative value smaller</param>
/// <param name="amountInPercent">True - grow / shrink in percent,
/// False - grow / shrink absolute</param>
public static void SetAllControlsFontSize(
System.Windows.Forms.Control.ControlCollection ctrls,
int amount = 0, bool amountInPercent = true)
{
if (amount == 0) return;
foreach (Control ctrl in ctrls)
{
// recursive
if (ctrl.Controls != null) SetAllControlsFontSize(ctrl.Controls,
amount, amountInPercent);
if (ctrl != null)
{
float oldSize = (float)ctrl.Font.Size;
float newSize =
(amountInPercent) ? oldSize + oldSize * ((float)amount / (float)100)
: oldSize + (float)amount;
if (newSize < 4) newSize = 4; // don't allow less than 4
var fontFamilyName = ctrl.Font.FontFamily.Name;
ctrl.Font = new Font(fontFamilyName, newSize);
};
};
}
This allows to grow or shrink the font size in percent like:
SetAllControlsFontSize(this.Controls, 20);
Or you can shrink the font size absolutely by a value of -4 like:
SetAllControlsFontSize(this.Controls, amount: -4, amountInPercent: false);
In both examples, all fonts will be affected by the change. You do not need to know the font family names, each control can have different ones.
Combined with this answer you can auto-scale fonts in your application based on Windows settings (which you can find if you right click on the desktop, then select Display settings, Scale and layout and modify the value "Change the size of text, apps, and other items" - in Windows 10 versions newer than build 1809 this is (re-)named as "Make everything bigger"):
var percentage = GetWindowsScaling() - 100;
SetAllControlsFontSize(this.Controls, percentage);
You should also limit the size to a certain maximum/minimum, based on your forms layout, e.g.
if (percentage > 80) percentage = 80;
if (percentage < -20) percentage = -20;
Likewise this is true for absolute values - note that in the code there is already a limit set: Practically, a font cannot be smaller than 4 em - this is set as minimum limit (of course you can adapt that to your needs).
Upvotes: 3
Reputation: 190
Just set the font of parent form. It will propagate through controls unless you set font on child control manually
Example code:
public MyForm()
{
InitializeComponent();
Font = new Font(new FontFamily("Microsoft Sans Serif"), 8f); //replace 8f with desired font size
}
From Control.Font
docs:
Remarks
The Font property is an ambient property. An ambient property is a control property that, if not set, is retrieved from the parent control. For example, a Button will have the same BackColor as its parent Form by default.
Tested in .NetFramework 4.6.2
and .Net6
Upvotes: 0
Reputation: 216293
A simple recursive function will traverse all the controls in your form and change the font size. You need to test it against your controls and look at the effect because in this code there is no exception handling
public void SetAllControlsFont(ControlCollection ctrls)
{
foreach(Control ctrl in ctrls)
{
if(ctrl.Controls != null)
SetAllControlsFont(ctrl.Controls);
ctrl.Font = new Font("Impact", ctrl.Font.Size - 4);
}
}
You can call it from your toplevel form passing the initial form's control collection
SetAllControlsFont(this.Controls);
Upvotes: 7