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.
PROPERTY | DESCRIPTION |
---|---|
Bold | True if the font is boldface |
FontFamily | Gets the font family |
Height | Gets the height of the font in the current graphics unit |
Italic | True if font is italicized |
Name | Gets the name of the font |
Size | Get the size of the font in the current graphics unit |
SizeInPoints | Gets the size of the font in points (1/72 inch) |
Strikeout | True if the font is struck out |
Style | Gets the style information |
Underline | True if the font is underlined |
Unit | Gets the graphics unit |
The code in Listing 11-11 creates ten random fonts and then displays them.
Listing 11-11: Generating Random Fonts
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; } } }; }
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.
Figure 11-11: Displaying random fonts