Using Fonts

Using Fonts

Fonts are GDI+ objects much like the pens and brushes discussed earlier in this chapter and are represented by the Font class. When text is displayed anywhere in a Windows Forms application, it’s done using a font. Most of the time, you can display text without explicitly specifying a font because controls and forms are always associated with a default Font object. However, there are many occasions when it’s useful to specify a particular font—perhaps you need to have some text that’s shown with a heavier, bolder font, or perhaps you prefer that a label or a section of text use a particular size of font.

Fonts used in Windows Forms application follow two specifications:

  • TrueType  A standard for fonts that was developed by Microsoft and Apple. This type of font was first used in Microsoft Windows 3.1. In the Font common dialog box, TrueType fonts are distinguished by a TT icon next to their name.

  • OpenType  An extension of the TrueType specification that was developed by Microsoft and Adobe.

These are the only types of fonts available in a Windows Forms application. In particular, the older raster fonts available in Win32 SDK applications aren’t supported.

Understanding the Vocabulary of Fonts

Working with fonts requires a unique vocabulary. A typeface is a specific style of drawing a character. Arial, Times New Roman, and Garamond are all names of typefaces. A collection of descriptions that describe how to draw a set of characters using the same display characteristics and the same typeface is a font. The font is traditionally referred to by its typeface name along with any style modifiers, as in Arial Bold and Garamond Italic.

Fonts can be monospace (sometimes called fixed-pitch fonts), such as Courier New and Lucida Console, or they can be variable-pitched, like Arial and Times New Roman. Characters drawn with a monospace font all have the same width, whereas in a variable-pitched font, the width of the characters varies on a character-by-character basis.

Serif fonts include an extra flourish at the end of strokes. Examples of serif fonts include Times New Roman, Courier New, and Garamond. Sans serif fonts don’t have serifs and include fonts such as Arial and Helvetica.

The FontStyle enumeration is used to identify common variations in fonts, using the following values:

  • Bold

  • Italic

  • Regular

  • Underline

  • Strikeout

  • Underline

Values from the FontStyle enumeration can be combined, so to specify a boldface italic font, you would use code like this:

FontStyle style = FontStyle.Bold ¦ FontStyle.Italic; 

Every font is part of a font family, which serves as a grouping for fonts that have the same typeface and similar styles. Variations of a font that differ based on their FontStyle characteristics are generally in the same font family. However, it’s not unusual for one typeface to be shared by multiple font families—for example, there are several font families that use variations of the Arial typeface.

The FontFamily class is used to interact with the font families installed on a computer. There are three constructors used to create FontFamily objects. The first constructor accepts a value from the GenericFontFamilies enumeration and creates an instance of FontFamily that represents one of the generic font families, as shown here:

FontFamily monoFont = new FontFamily(GenericFontFamilies.Monospace);

This code creates a FontFamily object that represents a generic monospace font family. The GenericFontFamilies enumeration values are provided in Table 14-12.

The second FontFamily constructor enables you to specify the font family by name and create a FontFamily object to represent it, as shown here:

FontFamily arialFamily = new FontFamily("Arial");

The third FontFamily constructor is used to create a FontFamily object based on a font that’s stored in an instance of PrivateFontCollection, which will be discussed in the next section.

In addition to the FontFamily constructors, you also can obtain references to FontFamily objects through static methods and properties exposed by the FontFamily class. The following static properties are used to obtain references to FontFamily objects that represent generic fonts:

  • GenericMonospace  Returns a FontFamily object that refers to a generic monospace font, such as Courier New

  • GenericSansSerif  Returns a FontFamily object that refers to a generic sans serif font, such as Microsoft Sans Serif

  • GenericSerif  Returns a FontFamily object that refers to a generic serif font, such as Times New Roman

In the next section, you’ll learn how to retrieve an array of FontFamily objects that represents all the installed fonts.

The FontFamily class exposes one non-static property—the Name property, which returns the name of the font family, as shown here:

FontFamily arialFamily = new FontFamily("Arial");
string familyName = arialFamily.Name; 

The FontFamily class exposes several useful methods, including the IsStyleAvailable method. If you attempt to create a font with an unsupported style, an exception will be thrown. For example, some font families don’t support the boldface or italic font styles. The IsStyleAvailable method provides a useful way to determine whether a specific font style is supported by a font family, as shown here:

if(arialFamily.IsStyleAvailable(FontStyle.Bold))
{
    // Font can be safely created.
    
    

}
Using the FontCollection Classes

The FontCollection base class is used to store a collection of fonts available for use. There are two sealed subclasses:

  • InstalledFontCollection  Class that represents the collection of fonts that are installed on the user’s computer

  • PrivateFontCollection  Class that represents a collection of fonts used for the application only and not installed in the operating system’s collection of installed fonts

The InstalledFontCollection class is useful when you want to determine whether a particular font family has been installed. If your application requires a specific font, you can use this collection to determine whether the font is available for use. The following code displays all the installed fonts in a message box:

static void Main() 
{
    StringBuilder familyNames = new StringBuilder();            
    InstalledFontCollection ifc = new InstalledFontCollection();
    FontFamily[] families = ifc.Families;
    foreach(FontFamily family in families)
    {
        familyNames.AppendFormat("{0}\n", family.Name);
    }
    MessageBox.Show(familyNames.ToString());
}

This example creates an instance of InstalledFontCollection and retrieves an array of FontFamily objects that represent all the fonts installed on the computer. Next the code iterates over the array of FontFamily objects and displays the names in a message box, as shown in Figure 14-13.

Figure 14-13.
A message box displaying currently installed font families.
Font Metrics

Fonts are measured using a variety of metrics, including points, em sizes, and design units. In this section, these terms are defined, and you’ll learn how to collect font metrics.

A good place to begin is with the point. A point is about 1/72 of an inch and is a common unit used to describe relative font sizes. On a computer screen, the point sizes don’t refer to physical dimensions and are really useful only for comparison purposes. The default font size for Windows is 10 points, whereas the default font size for Windows Forms is 8.25 points. A common unit of measurement in Windows Forms is the document unit, which is 1/300 of an inch, or about 4.16 document units per point.

When working with font metrics, you’ll often see references to the em size. An em is the point size of a given font. If the font is 10 points, the em size will be 10 points. A value of 2 ems is twice the size of the current font (for example, 20 points if the current font is 10 points).

The following methods from the FontFamily class can be used to collect information about font metrics:

  • GetCellAscent  Returns the vertical size reserved for an ascender (the portion of a font drawn above the baseline) for a specified font style

  • GetCellDescent  Returns the vertical size reserved for a descender (the portion of a font drawn below the baseline) for a specified font style

  • GetEmHeight  Returns the height of an em for a specified font style

  • GetLineSpacing  Returns the spacing between lines for a specified font style

Creating Fonts Programmatically

There are 13 versions of the Font constructor. These constructors create Font objects based on combinations of the font family, the size of the font, desired font styles, and other parameters.

A common reason to create a new Font object is to change one of the FontStyle values associated with the font. For example, you might have a menu item that retains the current font family but changes the style to boldface or italic. The following version of the Font constructor enables you to create a Font object by passing an existing Font object as a template along with a new FontStyle value, as shown here:

Font = new Font(oldFont, newStyle);

The following code uses this version of the constructor to enable or disable the boldface style for the font:

private void ToggleBoldStyle()
{
    // Get the current font and style.
    Font oldFont = Font;
    // Flip the Bold style flag.
    FontStyle newStyle = Font.Style ^ FontStyle.Bold;
    // Use the old font and the new style to create a new Font object.
    Font = new Font(oldFont, newStyle);
    // Clean up.
    oldFont.Dispose();
    Invalidate();
} 

This code toggles the boldface style for the text displayed in a form. First the current font is retrieved through the Font property. Next the form’s font style is retrieved, and the FontStyle.Bold value is toggled using a bitwise XOR operation. The new Font object is created using the new FontStyle value. The great thing about using this approach is that there’s no need to know anything about the current font—it’s easy to write a generic method that works with any font that’s currently assigned to a form or a control. The only problem with this approach is that font families aren’t required to supply fonts that include every possible combination of styles available in the FontStyle enumeration. If you attempt to create a font with a style that doesn’t exist, an exception will be thrown. To avoid an exception, use the FontFamily.IsStyleAvailable method to determine whether the new font style is supported, as described earlier.

The 12 remaining Font constructors can be arranged in six pairs, with one constructor in each pair accepting a FontFamily value as its first parameter, and the other constructor in each pair accepting the name of a font family as a string value. The first pair of constructors enables you to specify the font family and em size, as shown here:

FontFamily family = new FontFamily("Trebuchet MS");
Font labelFont = new Font(family, 20.0f);
Font statusFont = new Font("Garamond", 20.0f);

These two versions of the Font constructor create a Font object with default properties for the font style. The following pair of constructors enable you to specify values from the FontStyle enumeration that will be applied to the new Font object:

Font labelFont = new Font(family, 20.0f, FontStyle.Underline); 
Font statusFont = new Font("Garamond", 20.0f, FontStyle.Bold);

Although these constructors enable you to specify a font style, remember that any constructor that accepts a FontStyle parameter will throw an exception if a font can’t be created with the requested font style.

The next pair of constructors creates Font objects with measurement units set to a value other than the point size. The value passed as the GraphicsUnit parameter specifies which unit of measurement is used for the font size, as shown here:

Font labelFont = new Font(family, 
                          20.0f,
                          GraphicsUnit.Document);
Font statusFont = new Font("Garamond", 
                           20.0f,
                           GraphicsUnit.Document);

The next set of constructors combines the parameters of the previous two sets of constructors, enabling you to specify a FontStyle value and a value from the GraphicsUnit enumeration:

Font labelFont = new Font(family, 
                          20.0f,
                          FontStyle.Underline,
                          GraphicsUnit.Document);
Font statusFont = new Font("Garamond", 
                           20.0f,
                           FontStyle.Bold,
                           GraphicsUnit.Document); 

Values from the GraphicsUnit enumeration are provided in Table 14-13.

When creating a Font object, you can specify the desired character set using the following set of constructors:

// From WinGDI.h
const byte OEM_CHARSET = 255;
Font labelFont = new Font(family, 
                          20.0f,
                          FontStyle.Underline,
                          GraphicsUnit.Point,
                          OEM_CHARSET);
Font statusFont = new Font("Garamond", 
                            20.0f,
                            FontStyle.Bold,
                            GraphicsUnit.Point,
                            OEM_CHARSET); 

Unfortunately, there isn’t any enumeration supplied with the .NET Framework that represents the available values for character sets, so you have to look in the WinGDI.h header file from the Win32 Platform SDK and pull the values out manually, as was done for this example. You can download the Win32 Platform SDK from http://msdn.microsoft.com/downloads/default.asp.

The final set of Font constructors, shown in the following code, is used to specify whether the new Font object is a vertical font. The last parameter of these constructors is true if the font is a vertical font; otherwise, it’s false.

Font labelFont = new Font(family, 
                          20.0f,
                          FontStyle.Underline,
                          GraphicsUnit.Point,
                          OEM_CHARSET,
                          true);
Font statusFont = new Font("Garamond", 
                            20.0f,
                            FontStyle.Bold,
                            GraphicsUnit.Point,
                            OEM_CHARSET,
                            true);
Managing Font Properties

The properties exposed by a font are read-only because changing any of the properties would result in a new font. The most commonly used properties are listed here:

  • Bold  Boolean value that’s true for boldface fonts and false otherwise

  • FontFamily  Value from the FontFamily enumeration that identifies the font family for this font

  • Height  Height of the font

  • Italic  Boolean value that’s true for italic fonts and false otherwise

  • Size  Size of the font

  • SizeInPoints  Size of the font in points, regardless of the current Unit property setting

  • Strikeout  Boolean value that’s true for strikeout fonts and false otherwise

  • Style  Value that combines all values from the FontStyle enumeration that are applied to this font

  • Underline  Boolean value that’s true for underlined fonts and false otherwise

  • Unit  Value from the GraphicsUnit enumeration that identifies the units used by the Height, Width, and Size properties

The Font Common Dialog Box

Adding support for selectable fonts to an application is easy using Microsoft Visual C# .NET and the .NET Framework. The companion CD includes a new version of the SimpleEdit example originally presented in Chapter 13. The version included in this chapter enables the user to select the font used to display the edited text. The code required to make this change spans just a few lines, as shown below.

private void editFontMenuItem_Click(object sender, System.EventArgs e)
{
    FontDialog dialog = new FontDialog();
    dialog.Font = Font;
    if(dialog.ShowDialog() == DialogResult.OK)
    {
        Font = dialog.Font;
        Invalidate();
    }
}

This code is simple, but it improves the user’s experience with the SimpleEdit application because the user is now free to use any available font when editing a text file. The editFontMenuItem_Click method starts by creating an instance of the FontDialog class and then passes the form’s font to the common dialog box. As with the ColorDialog class, discussed earlier in this chapter, in the section “The Color Common Dialog Box,” it’s a good idea to pass the current context information (in this case, the font) to the dialog box before it’s displayed to the user. This lets the user see the current settings before making changes.



Part III: Programming Windows Forms