Previous Section  < Day Day Up >  Next Section

9.2. Drawing Text Strings

The Graphics.DrawString method is the most straightforward way to place text on a drawing surface. All of its overloaded forms take a string to be printed, a font to represent the text, and a brush object to paint the text. The location where the text is to be printed is specified by a Point object, x and y coordinates, or a Rectangle object. The most interesting parameter is an optional StringFormat object that provides the formatting attributes for the DrawString method. We'll examine it in detail in the discussion on formatting.

Here are the overloads for DrawString. Note that StringFormat is optional in each.

Overloads:


public DrawString(string, font, brush, PointF      

   [,StringFormat]);

public DrawString(string, font, brush, float, float

   [,StringFormat]);

public DrawString(string, font, brush, RectangleF  

   [,StringFormat]);

 


Example:


Font regFont = new Font("Tahoma",12);

String s = "ice mast high came floating by as green as emerald.";

// Draw text beginning at coordinates  (20,5)

g.DrawString(s, regFont, Brushes.Black, 20,5);

regFont.Dispose(); 


In this example, the upper-left corner of the text string is located at the x,y coordinate 20 pixels from the left edge and 5 pixels from the top of the drawing surface. If the printed text extends beyond the boundary of the drawing surface, the text is truncated. You may want this in some cases, but more often you'll prefer that long lines be broken and printed as multiple lines.

Drawing Multi-Line Text

Several Drawstring overloads receive a rectangle to define where the output string is drawn. Text drawn into these rectangular areas is automatically wrapped to the next line if it reaches beyond the rectangle's boundary. The following code displays the fragment of poetry in an area 200 pixels wide and 50 pixels high.


String s = "and ice mast high came floating by as green 

   as emerald."

// All units in pixels

RectangleF rf = new RectangleF(20,5,200,50); 

// Fit text in rectangle

g.Drawstring(s,regFont,Brushes.Black, rf); 


Word wrapping is often preferable to line truncation, but raises the problem of determining how many lines of text must be accommodated. If there are more lines of text than can fit into the rectangle, they are truncated. To avoid truncation, you could calculate the height of the required rectangle by taking into account the font (f), total string length(s), and rectangle width (w). It turns out that .NET Graphics.MeasureString method performs this exact operation. One of its overloads takes the string, font, and desired line width as arguments, and returns a SizeF object whose Width and Height properties provide pixel values that define the required rectangle.


SizeF sf = g.MeasureString(String s, Font f, int w);


Using this method, the preceding code can be rewritten to handle the dynamic creation of the bounding rectangle:


Font regFont = new Font("Tahoma",12);

String s = "and ice mast high came floating by as green 

   as emerald."

int lineWidth = 200;

SizeF sf = g.MeasureString(s, regFont, lineWidth);

// Create rectangular drawing area based on return 

// height and width

RectangleF rf = new RectangleF(20,5,sf.Width, sf.Height); 

// Draw text in rectangle

g.Drawstring(s,regFont,Brushes.Black, rf); 

// Draw rectangle around text

g.DrawRectangle(Pens.Red,20F,5F,rf.Width, rf.Height);


Note that DrawString recognizes newline (\r\n) characters and creates a line break when one is encountered.

Formatting Strings with the StringFormat Class

When passed as an argument to the DrawString method, a StringFormat object can provide a number of formatting effects. It can be used to define tab positions, set column widths, apply right or left justification, and control text wrapping and truncation. As we will see in the next section, it is the primary tool for creating formatted reports. The members that we will make heaviest use of are shown in Table 9-2.

Table 9-2. Important StringFormat Members

Member

Description

Alignment

A StringAlignment enumeration value:

StringAlignment.Center? Text is centered in layout rectangle.

StringAlignment.Far?Text is aligned to the right for left-to-right text.

StringAlignment.Near?Text is aligned to the left for left-to-right text.

TRimming

A StringTrimming enumeration value that specifies how to trim characters that do not completely fit in the layout rectangle:

StringTrimming.Character?Text is trimmed to the nearest character.

StringTrimming.EllipsisCharacter?Text is trimmed to the nearest

character and an ellipsis (...) is placed at the end of the line.

StringTrimming.Word?Text is trimmed to the nearest word.

SetTabStops

Takes two parameters: SetTabStops(firstTabOffset, tabStops)

FirstTabOffset?Number of spaces between beginning of line and first tab stop.

TabStops?Array of distances between tab stops.

FormatFlags

This bit-coded property provides a variety of options for controlling print layout when printing within a rectangle.

StringFormatFlags.DirectionVertical?Draws text from top-to-bottom.

StringFormatFlags.LineLimit?Only entire lines are displayed within the rectangle.

StringFormatFlags.NoWrap?Disables text wrapping. The result is that text is printed on one line only, irrespective of the rectangle's height


Using Tab Stops

Tab stops provide a way to align proportionate-spaced font characters into columns. To set up tab stops, you create a StringFormat object, use its SetTabStops method to define an array of tab positions, and then pass this object to the DrawString method along with the text string containing tab characters (\t).

Core Note

If no tab stops are specified, default tab stops are set up at intervals equal to four times the size of the font. A 10-point font would have default tabs every 40 points.


As shown in Table 9-2, the SetTabStops method takes two arguments: the offset from the beginning of the line and an array of floating point values that specify the distance between tab stops. Here is an example that demonstrates various ways to define tab stops:


float[] tStops = {50f, 100f, 100f};  //Stops at: 50, 150, and 250

float[] tStops = {50f};        // Stops at: 50, 100, 150


You can see that it is not necessary to specify a tab stop for every tab. If a string contains a tab for which there is no corresponding tab stop, the last tab stop in the array is repeated. Listing 9-1 demonstrates using tabs to set column headers.

Listing 9-1. Using Tab Stops to Display Columns of Data

private void RePaint(object sender, PaintEventArgs e)

{

   Graphics g = e.Graphics;

   Font hdrFont = new Font("Arial", 10,FontStyle.Bold);

   Font bdyFont = new Font("Arial", 10); 

   // (1) Create StringFormat Object

   StringFormat strFmt = new StringFormat();

   // (2) Define Tab stops

   float[] ts = {140,60,40};

   strFmt.SetTabStops(0, ts);

   // (3) Define column header text to be printed with tabs

   string header = "Artist\tCountry\tBorn\tDied";

   // (4) Print column headers

   g.DrawString(header, hdrFont, Brushes.Black,10,10,strFmt);

   // Print one line below header

   string artist = "Edouard Manet\tEngland\t1832\t1892";

   g.DrawString(artist,bdyFont,Brushes.Black,10,

                10 + bdyFont.GetHeight(), strFmt); 

   bdyFont.Dispose();

   hdrFont.Dispose();

}


Figure 9-3 shows the four-column output from this code. Note that the second column begins at the x coordinate 150, which is the first tab stop (140) plus the x coordinate (10) specified in DrawString.

Figure 9-3. Printing with tab stops


The unit of measurement in this example is a pixel. This unit of measurement is determined by the Graphics.PageUnit property. To override the default (pixels), set the property to a GraphicsUnit enumeration value梖or example, g.PageUnit = GraphicsUnit.Inch. Be aware that all subsequent drawing done with the Graphics object will use these units.

Core Note

The use of tab spaces only supports left justification for proportionate fonts. If you need right justification梐 virtual necessity for displaying financial data梡ass a rectangle that has the appropriate coordinates to the DrawString method. Then, set the Alignment property of StringFormat to StringAlignment.Far.


String Trimming, Alignment, and Wrapping

The StringFormat Trimming and Alignment properties dictate how text is placed within a RectangleF object. Alignment works as you would expect, allowing you to center, right justify, or left justify a string. Trimming specifies how to truncate a string that extends beyond the boundaries of a rectangle when wrapping is not in effect. The basic options are to truncate on a word or character.

The following code segments demonstrate some of the common ways these properties can be used to format text strings.

Example 1: Printing Without a StringFormat Object

Font fnt = new Font("Tahoma",10,FontStyle.Bold);

RectangleF r = new RectangleF(5,5,220,60);

string txt = "dew drops are the gems of morning";

g.DrawString(txt,fnt,Brushes.Black,r);

g.DrawRectangle(Pens.Red,r.X,r.Y,r.Width,r.Height);


Example 2: Printing with NoWrap Option

StringFormat strFmt = new StringFormat();

strFmt.FormatFlags = StringFormatFlags.NoWrap;

g.DrawString(txt,fnt,Brushes.Black,r,strFmt);


Example 3: Printing with NoWrap and Clipping on a Word

StringFormat strFmt = new StringFormat();

strFmt.FormatFlags = StringFormatFlags.NoWrap;

strFmt.Trimming = StringTrimming.Word;

g.DrawString(txt,fnt,Brushes.Black,r,strFmt);


Example 4: Printing with NoWrap, Clipping on Word, and Right Justification

StringFormat strFmt = new StringFormat();

strFmt.FormatFlags = StringFormatFlags.NoWrap;

strFmt.Trimming = StringTrimming.Word;

strFmt.Alignment = StringAlignment.Far;

g.DrawString(txt,fnt,Brushes.Black,r,strFmt);


StringFormat also has a LineAlignment property that permits a text string to be centered vertically within a rectangle. To demonstrate, let's add two statements to Example 4:


strFmt.Alignment = StringAlignment.Center;

strFmt.LineAlignment = StringAlignment.Center;


    Previous Section  < Day Day Up >  Next Section