Windows Forms 2.0 Programming (Microsoft .NET Development Series)
The TextRenderer class, located in the System.Windows.Forms namespace, is an alternative to the Graphics class for text rendering. Although Graphics and TextRenderer provide similar levels of text-rendering capabilities, the key difference between the two technologies is the underlying rendering API each one encapsulates; the Graphics class uses GDI+, and TextRenderer wraps GDI directly. Thus, when you need to render text using GDI, you can use TextRenderer to save the effort of writing interop code. TextRenderer provides two methodsDrawText and MeasureTexteach of which has plenty of overloads that almost parallel their Graphics DrawString and MeasureString counterparts: namespace System.Windows.Forms { sealed class TextRenderer { // Methods public static void DrawText(IDeviceContext dc, ...); public static Size MeasureText(IDeviceContext dc, ...} public static Size MeasureText(string text, ...); } } Both DrawText and MeasureText, the equivalents of Graphics.DrawString and Graphics.MeasureString, respectively, wrap GDI invocations outside the graphics scope that is native to your applications via GDI+, whose main element is the surface you're drawing to via the Graphics object.[8] But GDI doesn't know anything about that drawing surface, so you need to pass it a device context handle that's wrapped by an IDeviceContext reference to the surface you want to draw text on. This is why several overloads of both DrawText and MeasureText accept an IDeviceContext. Fortunately, the Graphics class implements IDeviceContext, so you can simply pass it to either method. [8] Although they are conceptually equivalent, it is highly recommended that you don't mix calls between Graphics and TextRenderer DrawXxx and MeasureXxx methods. There is another set of MeasureText overloads that don't require an IDeviceContext. However, you should prefer those that do because it allows MeasureText to more accurately determine the size needed to display a chunk of text. Here's how to determine how much space a chunk of text actually needs: void TextRendererForm_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; Size proposedSize = this.ClientRectangle.Size; // Calculate rendered text size Size size = TextRenderer.MeasureText( g, "Text To Measure", this.Font, proposedSize); } As you can see, calling the MeasureText method is quite similar to calling Graphics. MeasureString. In addition to support for passing an IDeviceContext object reference, the other important difference between MeasureText and MeasureString is that the former returns a Size object, and the latter returns SizeF; the entire TextRenderer implementation works with integers only. To render a string with DrawText is almost the same as using Graphics.DrawString, apart from passing an IDeviceContext reference: void TextRendererForm_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; // IDeviceContext Size proposedSize = this.ClientRectangle.Size; // Calculate rendered text size Size size = TextRenderer.MeasureText( g, "Text To Measure", this.Font, proposedSize); // Render text to calculated size Rectangle rect = new Rectangle(0, 0, size.Width, size.Height); TextRenderer.DrawText( g, "Text To Measure", this.Font, rect, Color.Black); }
Figure 6.11 illustrates the result. Figure 6.11. Measuring and Drawing Text with TextRenderer
Of course, this is pretty plain, particularly from the point of view of formatting. Therein lies another consistency with Graphics: the ability to pass special formatting details to both MeasureText and DrawText. Formatting with TextRenderer
As with Graphics.DrawString, overloads of both the TextRenderer.MeasureText method and the TextRenderer.DrawText method allow you to pass in a special formatting-oriented argument of type TextFormattingFlags: namespace System.Windows.Forms { [Flags] enum TextFormatFlags { // Default (Top, Left, and GlyphOverhangPadding) Default = 0, // Align text to top Top = 0, // Align text to left Left = 0, // Use glyph overhang in text line height GlyphOverhangPadding = 0, // Align text to horizontal center of the rectangle HorizontalCenter = 1, // Align text to right Right = 2, // Align text to vertical center of rectangle VerticalCenter = 4, // Align text to bottom Bottom = 8, // Word wrapping WordBreak = 16, // Render all text to a single line SingleLine = 32, // "\t" characters in text are turned into tabs ExpandTabs = 64, // Don't clip text partially outside layout rect NoClipping = 256, // Use external leading in text line height ExternalLeading = 512, // Don't show underscores at all NoPrefix = 2048, // Calculate text metrics using system font Internal = 4096, // Render text as if rendered to a TextBox TextBoxControl = 8192, // Trim file path by putting ellipsis in the middle PathEllipsis = 16384, // Trim to nearest character and show ellipsis EndEllipsis = 32768, // Copy the displayed string to source string ModifyString = 65536, // Render text in right-to-left order RightToLeft = 131072, // Trim to nearest word and show ellipsis WordEllipsis = 262144, // Don't line break wide chars NoFullWidthCharacterBreak = 524288, // Hide "&" chars intended as underscores HidePrefix = 1048576, // Only draw underscores in place of "&" PrefixOnly = 2097152, // Use Graphics object clipping PreserveGraphicsClipping = 16777216, // Use Graphics object transformations PreserveGraphicsTranslateTransform = 33554432, // Don't pad text NoPadding = 268435456, // Pad text left and right edges LeftAndRightPadding = 536870912, }
Using TextFormatFlags, it's easy to center-align a chunk of text that collapses lines of text on a word-by-word basis, replacing hidden text with ellipsis characters: void TextRendererForm_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; Rectangle rect = this.ClientRectangle; TextFormatFlags flags = TextFormatFlags.HorizontalCenter| TextFormatFlags.VerticalCenter| TextFormatFlags.WordEllipsis; TextRenderer.DrawText( g, "Text To Measure", this.Font, rect, Color.Black, flags); }
The output of this code is shown in Figure 6.12 Figure 6.12. Measuring and Drawing Centered Text with TextRenderer
In general, you will find a lot of crossover between the two text-rendering technologies, particularly from the formatting perspective. Furthermore, knowledge you gain using one technology will serve you well with the other. However, there are also differences between the two technologies that you need to be aware of. |
Категории