It seems that many people seem overly concerned about the differences between GDI+'s Font class and FontFamily class. Here's my take on it: A Font class represents a single font and a FontFamily class represents a group of fonts that share many characteristics. You might think of a font family as "Arial" and a font as "Arial, 10-point, italic."

When you draw strings with GDI+, you don't have much of a choice. You have to build a Font class. You can't draw a string with a FontFamily class.

When you build a Font class, you have the choice of starting with a FontFamily class or a String containing the name of a font family. You'll probably use a String if you're planning on building a Font class from one of the standard fonts found on a computer (e.g., Arial, Courier, and Times New Roman). On the other hand, if your font is a little less common, you probably will search the computer for a list of font families currently loaded on your computer. If you find the FontFamily class in the list of font families, then it's a simple matter of using the FontFamily class instead of the String containing the font family's name. In general, I don't find the FontFamily class that useful as I tend to use the more common fonts in my programs, but you might have more exotic tastes. Basically, to use the FontFamily class, just replace the String in the first parameter of the Font constructor with the FontFamily class.

The process of building a font is quite easy. You do it using the Font constructors. You will use three constructors most often. They are really the same except that parameters are defaulted for two of them.

The first constructor defaults nothing and takes the name of the font family and the unit size, the font style, and the graphics unit:

 Font *f = new Drawing::Font(S"Arial", 16, FontStyle::Bold, GraphicsUnit::Point); 

In most cases, fonts default to a graphics unit of pixels. Therefore, Font provides a constructor with the graphics unit defaulted to pixels:

 Font *f = new Drawing::Font(S"Arial", 16, FontStyle::Bold); 

In addition, most of the time you are going to work with the font in the regular font style (not boldface, italic, or underline). So, again, Font provides a default for this:

 Font *f = new Drawing::Font(S"Arial", 16); 

Even though the Font class has several properties (see Table 11-10), they are all read-only. In other words, you can't change a font once you have constructed it.

Table 11-10: Common Font Properties




True if the font is boldface


Gets the font family


Gets the height of the font in the current graphics unit


True if font is italicized


Gets the name of the font


Get the size of the font in the current graphics unit


Gets the size of the font in points (1/72 inch)


True if the font is struck out


Gets the style information


True if the font is underlined


Gets the graphics unit

The code in Listing 11-11 creates ten random fonts and then displays them.

Listing 11-11: Generating Random Fonts

start example
 namespace FontsGalore {     using namespace System;     using namespace System::ComponentModel;     using namespace System::Collections;     using namespace System::Windows::Forms;     using namespace System::Data;     using namespace System::Drawing::Text;     using namespace System::Drawing;     public __gc class Form1 : public System::Windows::Forms::Form     {     public:         Form1(void)         {             fonts = new Drawing::Font*[10];             fontstr = new String*[10];             // Used to generate random fonts             Single sizes[] = { 10.0, 12.5, 16.0 };             FontStyle fontstyles[] = {                 FontStyle::Regular, FontStyle::Bold,                 FontStyle::Italic,             (FontStyle)(FontStyle::Underline|FontStyle::Bold|FontStyle::Italic)             };             GraphicsUnit units[] = { GraphicsUnit::Point, GraphicsUnit::Pixel };             // Get all fonts on computer             InstalledFontCollection *availFonts = new InstalledFontCollection();             FontFamily *fontfamilies[] = availFonts->Families;             Random *rand = new Random();             Int32 ff, s, fs, u;             for (Int32 i = 0; i < fonts->Count; i++)             {                 s  = rand->Next(0,3);                 fs = rand->Next(0,3);                 u  = rand->Next(0,2);                 // Not all fonts support every style                 do {                     ff = rand->Next(0,fontfamilies->Count);                 }                 while (!fontfamilies[ff]->IsStyleAvailable(                     (FontStyle)fontstyles[fs]));                 // Display string of font                 fontstr[i] = String::Format(S"{0} {1} {2}",                     fontfamilies[ff]->Name,                     _box(sizes[s])->ToString(),                     String::Concat(__box(fontstyles[fs])->ToString(), S" ",                                  _box(units[u])->ToString()));                 // Create the font                 fonts[i] = new Drawing::Font(fontfamilies[ff], sizes[s],                                                (FontStyle)fontstyles[fs],                                                (GraphicsUnit)units[u]);             }             InitializeComponent();         }     protected:         void Dispose(Boolean disposing)         //...     private: System::ComponentModel::Container * components;     private: Drawing::Font *fonts[];     private: String *fontstr[];         void InitializeComponent(void)         {             this->AutoScaleBaseSize = System::Drawing::Size(6, 15);             this->ClientSize = System::Drawing::Size(292, 265);             this->Name = S"Form1";             this->Text = S"Many Fonts";             this->Paint +=                 new System::Windows::Forms::PaintEventHandler(this, Form1_Paint);         }     private:         System::Void Form1_Paint(System::Object *  sender,                                    System::Windows::Forms::PaintEventArgs *  e)         {             Graphics *g = e->Graphics;             Single lineloc = 0;             for (Int32 i = 0; i < fonts->Count; i++)             {                 // Display font                 g->DrawString(fontstr[i],fonts[i], Brushes::Black, 10, lineloc);                 // Calculate the top of the next line                 lineloc += fonts[i]->Height;             }         }     }; } 
end example

Deep within the code is the routine to get a list of all the font families on your system:

 InstalledFontCollection *availFonts = new InstalledFontCollection(); FontFamily *fontfamilies[] = availFonts->Families; 

After these two lines are run, you have an array of all FontFamilies on your computer. It is pretty easy, no? The only hard part is remembering to add the namespace System::Drawing::Text, which you need to get access to the InstalledFontCollection class.

Something you might want to notice is how I figured out where to start the next line of String. I did this by adding the height of the font to the current line y coordinate after I finished drawing with it:

 lineloc += fonts[i]->Height; 

Figure 11-11 shows one instance of FontsGalore.exe running. I doubt you will ever see the same combination of fonts displayed twice.

click to expand
Figure 11-11: Displaying random fonts

Managed C++ and. NET Development
Managed C++ and .NET Development: Visual Studio .NET 2003 Edition
ISBN: 1590590333
EAN: 2147483647
Year: 2005
Pages: 169 © 2008-2017.
If you may any questions please contact us: