It all stems back to a rather unfortunate implementation of Control.DefaultFont.   Raymond talked a bit about DEFAULT_GUI_FONT the other day, and mentioned that no one is using it anymore. 

Unfortunately, this is the default font for controls.  DEFAULT_GUI_FONT only changes with respect to DPI setting (Right click on desktop, Properties->Settings->Advanced->DPI Setting), and ignores the font setting (Right click on desktop, Properties ->Appearance->Font Size).

Why wasn’t it changed in Whidbey?

Kevin asks: Why can’t we just change it in Whidbey?  Well here’s why.

Ideally the font we would like to change it to is SystemFonts.IconTitleFont.  This is what Visual Studio uses, and if you don’t believe it, you can GetService for the IUIService yourself and grab a hold onto the DialogFont.

Unfortunately, with the old AutoScaleBaseSize implementation, rounding errors assigning in this font will make your buttons grow to 26 pixels high!

What has been fixed in Whidbey?
 
As much as we *really* wanted to, we could not change the default font.  There is good news though - we did fix a large number of the scaling problems by adding a new AutoScaleDimensions API.  Gone should be the problems of the rounding errors, UI that isn’t scaled because it’s added too late (AutoScaleBaseSize only scales stuff added before the Load event), and fingers crossed, visual inheritance should work a whole lot better.

If you're not sure what scaling is, check out the Windows Forms Layout article.

The Scoop on the SystemFonts class

As Raymond mentions in his comments there is no real “default font” in windows, there are a lot of different fonts that are correct for different pieces of UI.  These should all be exposed in Windows Forms 2.0 through the SystemFonts class. 

Note that these fonts are NOT like SystemBrushes and SystemPens, calling it creates a new font which must be disposed – e.g. if you’re using TextRenderer.DrawText(“foo”, SystemFonts.MenuFont); you’ve just leaked a font.

How do I get Tahoma in my app?

It’s a good question – there is one gotcha you have to know about.  You need to assign in the SystemFonts.IconTitleFont to the Font property of your form, and then refresh the font whenever the system has changed it.  The “refresh” part is done by hooking onto the UserPreferenceChanged event from the SystemEvents class. 

Note:  as always with static events, you have to unhook them in the dispose method, otherwise the static event holds open the lifetime of the form.

using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Win32;
namespace WindowsApplication1 {
    public class Form1 : Form {
        public Form1() {
            this.Font = SystemFonts.IconTitleFont;
            InitializeComponent();
            SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
        }

        void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) {
            if (e.Category == UserPreferenceCategory.Window) {
                this.Font = SystemFonts.IconTitleFont;
            }
        }

        protected override void Dispose(bool disposing) {
            if (disposing) {
                SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
                if (components != null) {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent() {
            this.AutoScaleMode = AutoScaleMode.Font;
            this.AutoScaleDimensions = new System.Drawing.SizeF(5, 13);
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Name = "Form1";
            this.Text = "Form1";
        }

    }
}


Why don’t my MenuStrips/ToolStrips inherit font from the form?

MenuStrip and ToolStrip use SystemFonts.MenuFont as their default font, whereas the other controls inherit their font by default (ultimately using whatever the form is set to – usually the Control.DefaultFont).