Click here to Skip to main content
11,637,415 members (66,926 online)
Click here to Skip to main content

Bypass Graphics.MeasureString limitations

, 22 Apr 2003 LGPL3 295K 85
Rate this:
Please Sign up or sign in to vote.
This sample code computes the width of the string, as drawn by Graphics.DrawString

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, <BR>                                                                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  = <BR>                                       { 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, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

Share

About the Author

Pierre Arnaud
Web Developer
Switzerland Switzerland

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.


You may also be interested in...

Comments and Discussions

 
SuggestionShorter method Pin
Member 1019106015-Apr-14 7:10
memberMember 1019106015-Apr-14 7:10 
Answeryet another solution: TextRenderer.DrawText instead of Graphics.DrawString Pin
Member 850679424-Oct-13 19:24
memberMember 850679424-Oct-13 19:24 
QuestionTextRenderer.MeasureText Pin
Senser2216-Aug-13 1:38
memberSenser2216-Aug-13 1:38 
GeneralMy vote of 5 Pin
Member 915697628-Aug-12 5:23
memberMember 915697628-Aug-12 5:23 
GeneralMy vote of 5 Pin
Sweegle21-Jul-12 9:12
memberSweegle21-Jul-12 9:12 
GeneralThanks! Pin
Alexandru Pupsa10-Jul-12 21:35
memberAlexandru Pupsa10-Jul-12 21:35 
GeneralMy vote of 5 Pin
manoj kumar choubey18-Feb-12 3:28
membermanoj kumar choubey18-Feb-12 3:28 
QuestionDoes it measure only width? Pin
Tushar Trivedi16-Mar-10 20:09
memberTushar Trivedi16-Mar-10 20:09 
AnswerRe: Does it measure only width? Pin
Pierre Arnaud16-Mar-10 20:22
memberPierre Arnaud16-Mar-10 20:22 
GeneralHey, this article has been pointed to by Patrick Smacchia (MVP C#, NDepend author) Pin
Pierre Arnaud23-Sep-09 8:36
memberPierre Arnaud23-Sep-09 8:36 
QuestionCalculating height? Pin
fuzzek2-Sep-08 23:32
memberfuzzek2-Sep-08 23:32 
AnswerRe: Calculating height? Pin
Pierre Arnaud3-Sep-08 1:17
memberPierre Arnaud3-Sep-08 1:17 
GeneralRe: Calculating height? Pin
Roland Li15-Sep-09 23:29
memberRoland Li15-Sep-09 23:29 
GeneralGraphics Argument Pin
cmschick15-Nov-07 7:58
membercmschick15-Nov-07 7:58 
Questionrichtextbox with the capability of inserting a table Pin
mahfuzdinish24-Jul-07 21:15
membermahfuzdinish24-Jul-07 21:15 
Generalthanks Pin
wuzhiqiang7-Nov-06 18:10
memberwuzhiqiang7-Nov-06 18:10 
GeneralFound great MSDN Article where such problem is solved... Pin
Norman-Timo3-Nov-06 5:42
memberNorman-Timo3-Nov-06 5:42 
GeneralRe: Found great MSDN Article where such problem is solved... Pin
LegoMindstorms10-Oct-07 7:09
memberLegoMindstorms10-Oct-07 7:09 
GeneralUsing GDI use DrawText with DT_CALCRECT Pin
gerard carbo18-Oct-06 0:32
membergerard carbo18-Oct-06 0:32 
GeneralMy way to elimonate extra width Pin
Meysam Naseri23-Sep-06 22:55
memberMeysam Naseri23-Sep-06 22:55 
GeneralRe: My way to elimonate extra width Pin
Martin Yle2-Dec-06 15:07
memberMartin Yle2-Dec-06 15:07 
GeneralRe: My way to elimonate extra width Pin
flend3-May-08 8:32
memberflend3-May-08 8:32 
GeneralRe: My way to elimonate extra width Pin
andre_dart4-May-09 6:57
memberandre_dart4-May-09 6:57 
GeneralRe: My way to elimonate extra width Pin
jeffcohen1235-May-10 2:18
memberjeffcohen1235-May-10 2:18 
GeneralProblem with FontStyle.Bold Pin
Christian Wikander14-Sep-06 23:08
memberChristian Wikander14-Sep-06 23:08 
GeneralI have no problems with MeasureString.... :)) Pin
super_24-Aug-06 21:19
membersuper_24-Aug-06 21:19 
GeneralRe: I have no problems with MeasureString.... :)) Pin
Sergey Alexander Gynech10-Sep-08 15:21
memberSergey Alexander Gynech10-Sep-08 15:21 
General2nd solution can work with trailing spaces Pin
MegaDave3127-Jul-06 8:42
memberMegaDave3127-Jul-06 8:42 
GeneralRe: 2nd solution can work with trailing spaces Pin
Bard Hustveit25-Nov-06 8:40
memberBard Hustveit25-Nov-06 8:40 
QuestionPossible Correction? Pin
Mons00n31-May-06 4:33
memberMons00n31-May-06 4:33 
AnswerRe: Possible Correction? [modified] Pin
Pierre Arnaud31-May-06 18:47
memberPierre Arnaud31-May-06 18:47 
GeneralAWESOME!!! Pin
secovel3-May-06 9:39
membersecovel3-May-06 9:39 
QuestionWhat about vb6? Pin
Adam Mendoza31-Mar-06 6:31
memberAdam Mendoza31-Mar-06 6:31 
QuestionHow to measure the width string in RichTextBox with different fonts Pin
lpbinh8-Mar-06 15:18
memberlpbinh8-Mar-06 15:18 
GeneralThanks! Pin
Charlene_8-Nov-05 0:46
memberCharlene_8-Nov-05 0:46 
GeneralDoes Not Work For Hypertext Label Pin
nbk33r126-Jul-05 16:24
membernbk33r126-Jul-05 16:24 
I have another odd ball issue related to this code too. For example... "www.digitial-string-measure.com"

Generates odd width length as well. HELP! LOL By the way, non-integer font does really whack the results, in the case above, it just makes the issue worse.

Changing the string-format to typograhic had no effect, subtracting .right - .left had not effect... but this is reasonable because .left always seems to be zero in my experience.

Confused | :confused:
Generalcode seems to work but i have some strange result :( Pin
Sn3b11-Jul-05 22:10
memberSn3b11-Jul-05 22:10 
GeneralStill not correct with special strings!!! Pin
Anonymous21-Jun-05 17:49
sussAnonymous21-Jun-05 17:49 
GeneralGraphics argument Pin
Anonymous1-Jun-05 5:07
sussAnonymous1-Jun-05 5:07 
GeneralRe: Graphics argument Pin
Pierre Arnaud1-Jun-05 19:52
memberPierre Arnaud1-Jun-05 19:52 
QuestionRe: Graphics argument Pin
Steven Rothwell22-Feb-09 14:31
memberSteven Rothwell22-Feb-09 14:31 
QuestionIs this a bug? Pin
Matthew Hayhurst18-May-05 3:54
sussMatthew Hayhurst18-May-05 3:54 
AnswerRe: Is this a bug? Pin
Pierre Arnaud18-May-05 19:43
memberPierre Arnaud18-May-05 19:43 
GeneralVery helpful Pin
smushkat4-Mar-05 17:50
susssmushkat4-Mar-05 17:50 
GeneralNumber of lines text wrapped. Pin
johannf21-Feb-05 6:16
memberjohannf21-Feb-05 6:16 
GeneralC code Pin
acostein4-Feb-05 18:46
memberacostein4-Feb-05 18:46 
GeneralA (possible) imrovement Pin
xaverbirrer5-May-05 4:48
memberxaverbirrer5-May-05 4:48 
Generalhighlighting Pin
sreejith ss nair27-Dec-04 21:28
membersreejith ss nair27-Dec-04 21:28 
QuestionWhat about Height Problem? Pin
Sameers (theAngrycodeR )11-Jul-04 12:57
memberSameers (theAngrycodeR )11-Jul-04 12:57 
Questionrect.Right + 1.0f? Pin
imessvb3-Jun-04 22:02
memberimessvb3-Jun-04 22:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150728.1 | Last Updated 23 Apr 2003
Article Copyright 2002 by Pierre Arnaud
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid