5,784,478 members and growing! (17,697 online)
Email Password   helpLost your password?
Multimedia » GDI+ » General     Intermediate

Bypass Graphics.MeasureString limitations

By Pierre Arnaud

This sample code computes the width of the string, as drawn by Graphics.DrawString
C#, Windows, .NET 1.0, .NET, Visual Studio, Dev

Posted: 14 Apr 2002
Updated: 22 Apr 2003
Views: 151,484
Bookmarked: 56 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
34 votes for this Article.
Popularity: 6.56 Rating: 4.28 out of 5
2 votes, 6.9%
1
1 vote, 3.4%
2
0 votes, 0.0%
3
5 votes, 17.2%
4
21 votes, 72.4%
5

Sample Image - measurestring.gif

Introduction

Graphics.MeasureString can be used to compute the height and width of a text string. Often, however, the dimensions returned do not match the size of what gets drawn on screen when calling Graphics.DrawString. The red box above shows the dimensions returned by Graphics.MeasureString, which is about an em too wide...

The differences between what is computed and what is really drawn on the screen are related to how GDI+ computes its widths when using hinting and antialiasing. Here are the  gory details. A known work-around is to make GDI+ display its string antialiased, in which case the measured width matches the displayed result. If you want to draw standard strings (to match the GUI appearance, for instance), you are left out.

First, naive solution

The code I present here can be inserted into any class which needs to compute the real width of a string (shown by the yellow background above). The trick I use to compute the real string width is to ask GDI+ to draw the string into a bitmap and then find the position of the last character by reading back the pixels. A few optimisations ensure that this gets done as fast as possible (small bitmap, few pixels).

static public int MeasureDisplayStringWidth(Graphics graphics, string text,
                                            Font font)
{
    const int width = 32;

    System.Drawing.Bitmap   bitmap = new System.Drawing.Bitmap (width, 1, 
graphics); System.Drawing.SizeF size = graphics.MeasureString (text, font); System.Drawing.Graphics anagra = System.Drawing.Graphics.FromImage(bitmap); int measured_width = (int) size.Width; if (anagra != null) { anagra.Clear (Color.White); anagra.DrawString (text+"|", font, Brushes.Black, width - measured_width, -font.Height / 2); for (int i = width-1; i >= 0; i--) { measured_width--; if (bitmap.GetPixel (i, 0).R != 255) // found a non-white pixel ? break; } } return measured_width; }

That's all, folks. Right-to-left scripts won't probably work with this piece of code.

Another solution...

It is also possible to get the accurate string geometry by using MeasureCharacterRanges, which returns a region matching exactly the bounding box of the specified string. This is faster and more elegant than the first solution I posted on CodeProject.

static public int MeasureDisplayStringWidth(Graphics graphics, string text,
                                            Font font)
{
    System.Drawing.StringFormat format  = new System.Drawing.StringFormat ();
    System.Drawing.RectangleF   rect    = new System.Drawing.RectangleF(0, 0,
                                                                  1000, 1000);
    System.Drawing.CharacterRange[] ranges  = 
{ new System.Drawing.CharacterRange(0, text.Length) }; System.Drawing.Region[] regions = new System.Drawing.Region[1]; format.SetMeasurableCharacterRanges (ranges); regions = graphics.MeasureCharacterRanges (text, font, rect, format); rect = regions[0].GetBounds (graphics); return (int)(rect.Right + 1.0f); }

Post Script

Both functions only work with non-empty strings. The second solution will strip the trailing spaces; the first solution will take them in account. Choose the one which best fits your needs

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Pierre Arnaud


Pierre Arnaud got a Ph.D. in computer science at the Swiss Federal Institute of Technology; he currently works both as an independent contractor on hardware and software projects at OPaC bright ideas and as a senior software designer at EPSITEC.

Pierre was a key contributor to the Smaky computer, a real time, multitasking system based on the Motorola 680x0 processor family.


Now, Pierre works on his spare time for the Creative Docs .NET project: it is a vector based drawing and page layout software based on .NET and AGG.


Occupation: Web Developer
Location: Switzerland Switzerland

Other popular GDI+ articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 25 of 55 (Total in Forum: 55) (Refresh)FirstPrevNext
GeneralCalculating height?memberfuzzek0:32 3 Sep '08  
GeneralRe: Calculating height?memberPierre Arnaud2:17 3 Sep '08  
GeneralGraphics Argumentmembercmschick8:58 15 Nov '07  
Questionrichtextbox with the capability of inserting a tablemembermahfuzdinish22:15 24 Jul '07  
Generalthanksmemberwuzhiqiang19:10 7 Nov '06  
GeneralFound great MSDN Article where such problem is solved...memberNorman-Timo6:42 3 Nov '06  
GeneralRe: Found great MSDN Article where such problem is solved...memberLegoMindstorms8:09 10 Oct '07  
GeneralUsing GDI use DrawText with DT_CALCRECTmembergerard carbo1:32 18 Oct '06  
GeneralMy way to elimonate extra widthmemberMeysam Naseri23:55 23 Sep '06  
GeneralRe: My way to elimonate extra widthmemberMartin Yle16:07 2 Dec '06  
GeneralRe: My way to elimonate extra widthmemberflend9:32 3 May '08  
GeneralProblem with FontStyle.BoldmemberChristian Wikander0:08 15 Sep '06  
GeneralI have no problems with MeasureString.... :))membersuper_22:19 24 Aug '06  
GeneralRe: I have no problems with MeasureString.... :))memberSergey Alexander Gynech16:21 10 Sep '08  
General2nd solution can work with trailing spacesmemberMegaDave319:42 27 Jul '06  
GeneralRe: 2nd solution can work with trailing spacesmemberBard Hustveit9:40 25 Nov '06  
GeneralPossible Correction?memberMons00n5:33 31 May '06  
AnswerRe: Possible Correction? [modified]memberPierre Arnaud19:47 31 May '06  
GeneralAWESOME!!!membersecovel10:39 3 May '06  
QuestionWhat about vb6?memberAdam Mendoza7:31 31 Mar '06  
GeneralHow to measure the width string in RichTextBox with different fontsmemberlpbinh16:18 8 Mar '06  
GeneralThanks!memberCharlene_1:46 8 Nov '05  
GeneralDoes Not Work For Hypertext Labelmembernbk33r117:24 26 Jul '05  
Generalcode seems to work but i have some strange result :(memberSn3b23:10 11 Jul '05  
GeneralStill not correct with special strings!!!sussAnonymous18:49 21 Jun '05  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 22 Apr 2003
Editor: Chris Maunder
Copyright 2002 by Pierre Arnaud
Everything else Copyright © CodeProject, 1999-2009
Web19 | Advertise on the Code Project