Monday, December 12, 2005

.NET headache - MeasureString

I've been working on a .Net custom control that displays a mix of text and graphics in a flow layout. The work required that I know the exact size of text strings in order to position the next widget relative to the previous string. .Net provides a method called MeasureString that you would think solves the problem but in fact it doesn't. MeasureString has the documented behavior of including 'a small amount of extra space before and after the string to allow for overhanging glyphs' (link).
While I'm sure there was a good reason for doing this, it would seem prudent for MS to also give developers a straight forward way of knowing the actual size of the string. The help for MeasureString mentions that if you want to know the real size of the string you should use another method called MeasureCharacterRanges(). While MeasureCharacterRanges can provide the answer, calling it with the proper settings is not exactly obvious. I found a bunch of chatter out on the web (circa 2002) about the issue but no simple solutions, so I decided to blog mine. Here's a version of a method that does what I needed that's as simple as I could make it. Most people probably know this already but if you're like me and new to .NET, maybe this will save you some grief.

public static Size JustMeasureTheDamnString(Graphics graphics, string str, Font font)
CharacterRange[] characterRanges = {new CharacterRange(0, str.Length)};
SizeF sizef = graphics.MeasureString(str, font);
RectangleF layoutRect = new RectangleF(0, 0, sizef.Width, sizef.Height);
StringFormat stringFormat = new StringFormat();
stringFormat.FormatFlags = StringFormatFlags.NoClip |
Region[] stringRegions;
stringRegions = graphics.MeasureCharacterRanges(str, font, layoutRect,
if (regions.Length == 0)
return Size.Empty;
return regions[0].GetBounds(g).Size.ToSize().
Post a Comment
The Out Campaign: Scarlet Letter of Atheism