Dynamic Graphic Text Resizing

4/7/2010

Darren Flatt, Founder, voidmobile

January 2008

Summary

The Windows Mobile operating system runs on a variety of devices, many of which have different screen resolutions. The varying screen sizes and resolutions can be a challenge to developers who are attempting to reach the largest possible audience. One of the many challenges developers face is displaying graphics with GDI+ that adapt to different screen sizes. A simple class that allows graphical strings to be displayed in a size that fits the screen can help developers write applications in this dynamic environment.

Download DynamicGraphicTextResizing.msi from the Microsoft Download Center.

Applies To

Microsoft Windows Mobile

The.NET Compact Framework

Microsoft Visual Studio 2005

Microsoft Visual Studio 2008

C#

GDI+

Introduction

The MeasureString Method at a Glance

Enhancing MeasureString

Putting It Together

Conclusion

Introduction

When developing a user interface for mobile applications, varying screen sizes and resolutions can cause many challenges. If you are creating an internal corporate line of business application, you may have some control over the devices that are used and can then limit the applications’ supported screen resolutions. However, in some cases you cannot control the target device for your application. If you have a commercial product that you want to run on phones, you will have no control over which particular devices are used with the application. (Microsoft Windows Mobile, for example, is supported on many devices with differing screen resolutions.) You would undoubtedly want your application to be available to the widest possible audience in order to maximize its success, and that means making your application suitable for a number of different screen resolutions. Drawing graphics that fit the screen is one of the challenges of supporting such a wide variety of device screen resolutions.

You may think that you would only utilize strings generated with GDI+ for drawing charts, graphs, or other graphical data visualization. You can, however, use graphics combined with Windows Form (WinForm) controls to provide an enhanced user experience by accommodating different resolutions. Graphic strings are also useful if you want to display text in a format where the user cannot copy the text and paste it elsewhere.

In the Microsoft .NET Compact Framework and the full Microsoft .NET Framework, the MeasureString method is provided for developers who want to find out if their graphic string is going to fit into available space when displayed. The use of MeasureString by itself does not accomplish what a developer would require to adapt graphic strings to a variable screen resolution. You must do a little extra work if you want to effectively adapt graphic text fonts to a given amount of screen real estate.

In order to solve this problem, you will need a simple method for dynamically resizing a text graphic based upon its container size.

The MeasureString Method at a Glance

The MeasureString method is simple. It is defined as follows:

public System.Drawing.SizeF MeasureString(string text, System.Drawing.Font font)

The Text argument is the string that you want to display graphically. The Font argument is a font object that defines the font that will be used for the string display.

A SIZEF structure is returned when MeasureString is called. The SIZEF structure is an ordered pair of floating point numbers indicating the minimum size of a rectangle that will support the proper display of the string. The two SIZEF structure properties that provide sizing information are Height and Width. In this case, the rectangle defines the minimum area required to fully draw out the given string displayed in the indicated font with no truncation.

A simple example using MeasureString would look like the following:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
   Graphics g = e.Graphics;
   
   Font f = new Font("Arial", 10, FontStyle.Regular);
   
   SizeF TestSize = g.MeasureString("Freedom of Choice",f);
   
   // Get the size of the proper rectangle for display
   float fHeight = TestSize.Height;
   float fWidth = TestSize.Width;
}

As you can see, we can easily get the height and width dimensions for the display rectangle with a simple font object and string. However, while MeasureString tells us the space needed to display the string, it does not provide a mechanism to make the string display in available space.

Enhancing MeasureString

So how do we use the MeasureString method to give us an appropriate font to allow the desired text to fit into the space provided? We can make our own special class that utilizes MeasureString but provides us with the information required to display the string properly. The example class I have provided is called FontAdjustment. The FontAdjustment class has one method, GetAdjustedFont, which returns the proper font size for a given container. We will assume that obtaining a font that fits the width of the container will also provide an adequate height. The GetAdjustedFont method is as follows:

public Font GetAdjustedFont(Graphics GraphicRef, string GraphicString, Font OriginalFont, int ContainerWidth, int MaxFontSize, int MinFontSize, bool SmallestOnFail)
{
   // We utilize MeasureString which we get via a control instance           
   for (int AdjustedSize = MaxFontSize; AdjustedSize >= MinFontSize; AdjustedSize--)
   {
      Font TestFont = new Font(OriginalFont.Name, AdjustedSize, OriginalFont.Style);

      // Test the string with the new size
      SizeF AdjustedSizeNew = GraphicRef.MeasureString(GraphicString, TestFont);

      if (ContainerWidth > Convert.ToInt32(AdjustedSizeNew.Width))
      {
   // Good font, return it
         return TestFont;
      }
   }

   // If you get here there was no fontsize that worked
   // return MinimumSize or Original?
   if (SmallestOnFail)
   {
      return new Font(OriginalFont.Name,MinFontSize,OriginalFont.Style);
   }
   else
   {
      return OriginalFont;
   }
}

The parameters for GetAdjustedFont are as follows:

GraphicRef

Graphics

The graphics object you are using to draw.

GraphicString

String

The string you want to display.

OriginalFont

Font

A font object that represents the initial font with which you will draw the string.

ContainerWidth

Int

The width of the container inside of which you are attempting to draw the string.

MaxFontSize

Int

The maximum size of font that you wish to draw.

MinFontSize

Int

The minimum size of font that you wish to draw.

SmallestOnFail

Bool

If the string cannot fit within the ContainerWidth, SmallestOnFail will function as follows. If true, it will return a font that is the MinFontSize. If false, it will return a font that is the OriginalFontSize.

ReturnValue

Font

A font object for use in drawing a graphic string.

Putting It Together

Now that we have the FontAdjustment class, we can put it to use and start properly sizing graphic strings. In this example, strings will be drawn on two separate panels. To initialize, we must set some font defaults and initialize the DefaultFont object. DefaultFont is the base font with which we will attempt to draw all of the strings. Here, DefaultFont is set in the load event of the form.

// Font and Brush for the text graphics
int FontSizeDefault = 12;
int FontSizeMinimum = 7;
Font DefaultFont;
StringBrush = new SolidBrush(Color.Black);

private void FormMain_Load(object sender, EventArgs e)
{
   DefaultFont = new Font("Tahoma", FontSizeDefault, FontStyle.Regular);
}
   

For the non-adjusted DrawString call, we just utilize the DefaultFont object, call DrawString, and assume it all went to plan.

private void pnlDefault_Paint(object sender, PaintEventArgs e)
{
   Graphics g = e.Graphics;
   g.DrawString(g,"Windows Mobile Development", DefaultFont, StringBrush, 1, 1);
} 

The string may or may not fit the panel. If we need to have a properly sized string, we add a call to GetAdjustedFont prior to executing DrawString. This step will ensure that the font object being used has the correct size.

private void pnlLarge_Paint(object sender, PaintEventArgs e)
{
   Graphics g = e.Graphics;
   FontAdjustment fa = new FontAdjustment();
   Font AdjustedFont = fa.GetAdjustedFont(g,"Windows Mobile Development",     
      DefaultFont, pnlLarge.Width, FontSizeDefault, FontSizeMinimum, true);
         
   g.DrawString("Windows Mobile Development", AdjustedFont, StringBrush, 1, 1);
}

You can see the results of font adjustement in the example shown in Figure 1. Note how the strings adjust to the container until they reach the smallest desirable font size.

Bb986765.d0b5c54b-adf4-45e0-b08a-1669239eaed5(en-us,MSDN.10).gif

Figure 1. The FontAdjustment Class Sample

Conclusion

Using the graphics capability of the .NET Compact Framework can allow you to enhance the users’ experience of your application. Windows Mobile has a very dynamic hardware environment that directly impacts the software you develop. Remember to take that dynamic environment into account, and you will improve your mobile application’s chance of success. Utilizing a custom classes such as FontAdjustment will provide an easy-to-use solution for developing applications that work well in this dynamic environment.

Author Bio

Darren Flatt is the founder of voidmobile, a Houston, Texas-based technology consulting and software development firm that focuses on mobile solutions. He also serves as Technology Director for Argent Consulting Services which develops enterprise regulatory compliance software. Darren has over 16 years of experience in the commercial software industry. In 2005 he co-founded NetPerceptor, a software company that produced one of the first enterprise mobile device management products for Windows Mobile. NetPerceptor was acquired by Patchlink (now Lumension) in 2006. He enjoys researching how to make user interfaces on Windows Mobile better for users, as well as making mobile devices better managed and integrated. Darren is a graduate of the Bauer College of Business, University of Houston. You can find Darren online at https://www.darrenflatt.com or contact him at darren.flatt@voidmobile.com.