Windows Forms 2.0 Programming (Microsoft .NET Development Series)
In general, text is rendered with a specific font to a specific location, and both Graphics and TextRenderer do that quite nicely. So, you might be wondering why there are two textrendering technologies in the .NET Framework. The Graphics class's text-rendering capabilities are powerful, but they suffer from several key problems, including weak internationalization support for complex scripts (such as Arabic), a lack of visual consistency between Windows Forms applications and the Windows shell, and performance. Unfortunately, although Microsoft tried, it could not refactor Graphics to solve these problems, because of inherent limitations in the technology. These problems are solved by GDI, however, so Microsoft created TextRenderer to provide a managed wrapper around GDI that, for Windows Forms applications, simplifies access to those features missing from Graphics. The resulting implementation is powerful, and the union of functionality between the two technology sets is reasonably large. As with most competing technologies, however, the union is not 100%. Instead, each technology is the best tool for a particular job. What follows is a discussion of the key issues you should consider to help you decide. Shell Consistency
The Windows shell uses GDI to render certain UI elements with a consistent font. For example, given a shell default button font of "Tahoma 8pt," Graphics and TextRenderer produce slightly different results, as illustrated in Figure 6.13 Figure 6.13. Comparing Shell Consistency (with VS05 | Tools | Options Dialog Buttons) (See Plate 14)
If you look closely, you can see that the TextRenderer output is consistent with the font used in the VS05 dialog, unlike Graphics, even though the same font is used: // ShellConsistencyForm.cs partial class ShellConsistencyForm : Form { // Draw OK button using Graphics void gOKButton_Paint(object sender, PaintEventArgs e) { // Draw button background ... // Render text using( StringFormat format = new StringFormat() ) using( Font font = new Font("Tahoma", 8) ) { format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; e.Graphics.DrawString( "OK", font, Brushes.Black, this.gOKButton.ClientRectangle, format); } } //Draw OK button using TextRenderer void tOKButton_Paint(object sender, PaintEventArgs e) { // Draw button background ... using( Font font = new Font("Tahoma", 8) ) { TextFormatFlags format = TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter; TextRenderer.DrawText( e.Graphics, "OK", font, this.tOKButton.ClientRectangle, this.ForeColor, format); } } ... } Being consistent with the shell is a great feature for applications in general and for reusable controls in particular. If you need to ensure that your visuals are consistent with the shell, you should prefer TextRenderer. Internationalization
Shell integration is also important for internationalization-ready applications, which must deal with rendering in a variety of languages, including complex scripts, that are determined by the shell. A script is the set of characters for a particular language, and a complex script is a script with special processing requirements, including the following:[9] [9] An outline of complex scripts can be found at http://www.microsoft.com/globaldev/DrIntl/faqs/Complex.mspx#E6 (http://tinysells.com/17).
Support for handling these issues is native to GDI and is used by Windows to render text for multiple languages.[10] If you've played with the Windows XP Language Bar and installed various language packs, you're familiar with this. Because TextRenderer wraps GDI, it naturally inherits the ability to render complex scripts with the same accuracy as Windows. Although you can render text for complex scripts using Graphics, you are unlikely to achieve the same level of quality as TextRenderer because of GDI+ limitations. Figure 6.14 demonstrates the difference in quality when you render Sinhala script using an appropriate font. [10] Specifically, the Windows Unicode Script Processor, or Uniscribe (usp10.dll) in Windows XP. Figure 6.14. Comparing Complex Script Output (Script=Sinhala, Font=DinaminaUniWeb 30pt)
In Figure 6.14, you can see that Sinhala uses combined characters, and Graphics can't combine characters while TextRenderer can.[11] From this example, it is clear that you should favor TextRenderer if your Windows Forms applications or custom controls require custom text rendering and need to support internationalization. [11] http://si.wikipedia.org/wiki/Wikipedia:Sinhala_font (http://tinysells.com/18). Thanks to Miguel Lacouture-Amaya from Microsoft for help in creating the complex script sample. Device-Independent Drawing
Internationalization attempts to provide language independence. Another type of independence that is a key feature of GDI+ and the Graphics object is device independence. This means that you render to a logical surface provided by the Graphics object, which wraps and paints to a physical surface, such as a screen or a printer. Consequently, the Graphics object you are handed has intimate knowledge of the physical surface, including the units to draw in, such as pixels (screen) or dpi (printer). Such intimacy allows you to draw to the Graphics object, which then performs scaling as required to match the units of the physical surface to which your stylings are eventually rendered. Thus WYSIWYG (what you see is what you get) is enabled. Figure 6.15 shows that what you see in a text box is what you get when printed, without the need to write any code other than drawing a string to a Graphics object using Graphics.DrawString. Figure 6.15. Graphics.DrawString Rendering Text to a Printer (Output Scanned) at Same Font as Text Box
From a device point of view, TextRenderer has no concept of independence. It was designed and built to render to one device, the screen, and this means that it knows only one set of units (pixels) and one scale. This subverts WYSIWYG, as shown in Figure 6.16 Figure 6.16. TextRenderer.DrawText Rendering Text to a Printer (Output Scanned) at Same Font as Text Box
If you want to use a TextRenderer to output to a different device, such as a printer, you need to convert the scale of your output to suit the target device. Although it's possible to do this, it's problematic for two reasons. First, you need to write one set of code to scale your TextRenderer output for each device you intend to target. Second, any manual scaling may lead to a loss of precision that will affect your ability to support WYSIWYG output. Therefore, for WYSIWYG output to multiple devices, Graphics provides a more accurate and simplified model. Font Edge Smoothing Support
Certain devices have special text-rendering considerations beyond scaling. For example, LCD screens produce blocky text output that needs font edge smoothing technology to make it more visually appealing. Windows XP supports three smoothing modes: no smoothing, "Standard" smoothing, and "ClearType" smoothing.[12] [12] These can be set from Control Panel | Display | Appearance | Effects. Both Graphics and TextRenderer render text to suit the current smoothing mode without intervention on your part. Up to a point, they are comparable. Table 6.4 illustrates the effect of no smoothing, Standard smoothing, and ClearType smoothing for both text-rendering technologies, using a "Microsoft Sans Serif 70 pt" character.
As you can see, the two technologies are equivalent for no smoothing and Standard smoothing. However, things go awry when ClearType is the smoothing mode. For no apparent reason, text rendered by Graphics using Microsoft Sans Serif (66 points and up) loses the antialiasing effect of ClearType. You can use text-rendering hints to influence the antialiasing applied to Graphics-rendered text, but you fall out of the sphere of influence exerted by the shellwide font edge smoothing mode. If you need your customrendered text to conform to the current shell smoothing mode, TextRenderer is the more consistent option. Performance
The performance of your output can be as important as how it eventually looks on your target device, particularly to screens, which often need to support high paint and refresh speeds. Because TextRenderer wraps GDI directly, it provides a higher-performance experience than using GDI+. For example, testing on the machine on which this chapter was typed demonstrated that text-rendering speeds for TextRenderer were approximately three times as fast as equivalent rendering by the Graphics object. Make sure you test appropriately if performance is an issue for your applications. Integration with GDI+ Graphical Rendering
Often, rendering performance is a factor of rendering both textual and graphical output together. One benefit of rendering text using a Graphics object is the ability it gives you to integrate text output with the graphical capabilities of GDI+. A simple example that you've already seen is the ability to turn on antialiasing to ensure smoothly printed fonts; in this case, what was applied to the Graphics object was implicitly applied to the rendered text, along with all the other nontextual graphical output. Similarly, we cited a more complex example in which we used a GraphicsPath object to simulate an outline-only font. Unfortunately, this benefit isn't available using TextRenderer because it bypasses GDI+ and, by association, the capability of both Graphics and GraphicsPath objects to integrate with it. Text-Formatting Comparison
Although both Graphics and TextRenderer offer a truckload of formatting options, if you use the StringFormat class and TextFormatFlags enumeration, respectively, a one-to-one parity does not exist, as outlined in Table 6.5.
One other feature notably missing from TextRenderer is text-rendering hints, because these are set via the Graphics object and thus have no effect on TextRenderer output. Integration
Because of TextRenderer's ability to paint text that's consistent with the Windows shell and because it supports internationalization, TextRenderer is now responsible for handling text-rendering duties for several Windows Forms controls, including Button, Label, TextBox, RadioButton, and CheckBox. However, this could be a problem if your application, overall, uses the Graphics text-rendering approach; there could be perceivable visual inconsistencies between the Windows Forms controls and your custom text-painting output. This is a likely scenario for all applications written for Windows Forms 1.x that you upgrade to Windows Forms 2.0. Fortunately, those controls that do paint their text elements with TextRenderer come with a compatibility switch that you can use to determine which text-rendering technology to use. The switch is exposed from each of these controls as the Boolean UseCompatibleTextRendering property. By default, UseCompatibleTextRendering is set to false, indicating that TextRenderer should be used. You set it to true to ensure that these controls instead render text using Graphics, most easily from the Properties window, as shown in Figure 6.17. Figure 6.17. Configuring a Control to Use Graphics Instead of TextRenderer
A nice benefit of setting UseCompatibleTextRendering from the Properties window is that you see the results immediately in the Windows Forms Designer. But if you have a lot of controls to change compatibility on, this approach could become tedious. Instead, you can invoke the Application.SetCompatibleTextRenderingDefault method to force all controls to use one model irrespective of the values of their own UseCompatibleTextRendering properties. By default, VS05 includes the call to SetCompatibleTextRenderingDefault in the wizard-generated Program.cs file: // Program.cs static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); // Make controls use TextRenderer Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } }
As with UseCompatibleTextRendering, passing false to SetCompatibleTextRenderingDefault means that TextRenderer is used, and passing true ensures that Graphics is used. If you're developing for Windows Forms 2.0 right off the bat, it's unlikely you'll need to fiddle with these settings unless you decide to use Graphics to render text in your applications or custom controls. |
Категории