Introduction
A noticeable problem .NET developers may have when they design their application is making it appear perfect on any recent Windows platform such as Windows 2000, Windows XP and the current Windows Vista. Before I installed Visual Studio 2005 on a fresh Windows Vista install, I candidly thought that the .NET runtime would have automatically solved the issue. This is true, but only with menus and status bars. If you are looking for compatibility between Windows 2000 and XP platforms, there is actually no problem. The issue is much more tricky if you want perfectly identical application displays on both Windows 2000/XP and Windows Vista. The reason is that Windows Vista:
- Has a new default font (Segoe UI vs. Tahoma)
- Has a new default font size (9.25 vs. 8.25)
Of course, designing a number of different versions for any different OS is not, in most cases, an option. My goal was to find an easy way to update my applications in order to display the right font and the right size according to the Windows OS and theme, without having to completely redesign them. The main difficulty is that the new Vista OS fonts have a different size and geometry.
A simple approach
The first idea is obvious: if the user is running Vista, then change to the SegoeUI font family with size 9.25 points for any control. Much better than that is to ask the .NET runtime, which is the default font for the UI currently in use. In this way, we may be confident that the solution will work for any past and future OS and theme. So, in order to update an application with the correct default font, we may use the SystemFonts
class introduced in .NET 2.0. After some research, I discovered that...
SystemFonts.MessageBoxFont
...defaults to Segoe UI 9.25 on Windows Vista with Vista Theme and, for example, to Tahoma 8.25 on Windows XP with XP Theme. If we do not want to re-design our application, we could apply a post-initialization code that simply adjusts any control's font. We position it just below the Windows Forms initialization code:
InitializeComponent();
foreach (Control c in this.Controls)
{
c.Font = new Font(SystemFonts.MessageBoxFont.FontFamily.Name, 8.25f);
}
The problem with this approach is that we lose any modification we made to our control font in the design view. So, for instance, if we set Label 1 to have font bold
, we just lose this setting and get a normal style. A better approach is the following:
foreach (Control c in this.Controls)
{
Font old = c.Font;
c.Font =
new Font(SystemFonts.MessageBoxFont.FontFamily.Name,
8.25f, old.Style);
}
By doing this, we retain all information about the control font. We can just modify the font family and get the size and style we defined with, for instance, the Visual Studio form designer. This could be an optimal solution if it were not for the fact that Windows Vista now defaults to 9.25 point font size. We could just say that if the user is running Vista, then adjust to 9.25, else set 8.25 font size. The problem with this pseudo-algorithm is that we stick to a particular OS -- Vista, in this case -- and we just miss the fact that the user may have Windows Vista, but she may be using the classic theme. In this case, her default font is Tahoma 8.25. Again, we use SystemFonts
to get a more universal solution:
foreach (Control c in this.Controls)
{
Font old = c.Font;
c.Font =
new Font(SystemFonts.MessageBoxFont.FontFamily.Name,
SystemFonts.MessageBoxFont.Size, old.Style);
}
Controls with custom size
We have now engineered a solution that, with a bunch of lines of code, adjusts our application so that it uses the correct default font for any combination of Windows OS and theme. A small problem arises when we use different or custom font sizes in the same form because we change the font and size of any control in the form. A suggestion may be to set the Tag
property of the control to something -- i.e. "custom" -- so that the re-size of the control may be skipped:
foreach (Control c in this.Controls)
{
Font old = c.Font;
float size = c.Font.Size;
if (c.Tag == null)
{
size = SystemFonts.MessageBoxFont.Size;
}
c.Font =
new Font(SystemFonts.MessageBoxFont.FontFamily.Name,
size, old.Style);
}
Even simpler
A problem with the above approach is that it assigns a new Font
object to any control on the form. There may be an even simpler approach that consists of setting the default font for the form. Thanks go to Georgi Atanasov for pointing this out:
Font sysFont = SystemFonts.MessageBoxFont;
this.Font = new Font(sysFont.Name, sysFont.SizeInPoints, sysFont.Style);
In this case, any control of your form will get the correct font on any theme and will change accordingly. This approach works if you DO NOT modify the Font
property of your controls, either directly in the code or in the Design View. In other words, the controls with a Font
property set will retain their font. This can be just the expected behavior if we take care to modify the font property only for the controls that we want to have a different font than the default. Often, however -- especially if we work in a team where the interfaces come from designers rather than programmers -- this is not the case and we have to test on any theme to be sure of the results. Anyway, this latest solution is obviously more elegant.
Conclusions
The decision to dramatically change the look of the Windows Vista operating system heavily affects the existing application. The question is of sticking to the old style or designing a whole new user interface. My article just proposes a little escamotage to avoid redesign and to have a user interface that follows the user's operating system theme. Of course, this is not wholly satisfactory. For instance, labels should be adjusted in width and height while passing from 8.25 to 9.25 point size and a lot of other small fixings are to be made. However, I think this could be a good starting point.
History
- 29 June, 2007 -- Original version posted
- 19 July, 2007 -- Article updated