Click to See Complete Forum and Search --> : Graphics.MeasureString not returning expected size


miteshpandey
September 6th, 2005, 11:51 AM
protected override void OnPaint(PaintEventArgs e)
{
// Set up string.
string measureString = "Measure String";
Font stringFont = new Font("Arial", 16);
// Measure string.
SizeF stringSize = new SizeF();
stringSize = e.Graphics.MeasureString(measureString, stringFont);
// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(
new Pen(Color.Red, 1),
0.0F, 0.0F, stringSize.Width, stringSize.Height);
// Draw string to screen.
e.Graphics.DrawString(
measureString,
stringFont,
Brushes.Black,
new PointF(0, 0));
}


The above is the code copied from MSDN exactly. It produces the following screenshot.

The problem is that you can see a small gap between the message and the right edge of the rectangle enclosing the message. The gap is about one character of the message.

If I use a smaller font the gap becomes about 3 characters of the message.


e.Graphics.DrawRectangle(
new Pen(Color.Red, 1),
0.0F, 0.0F, stringSize.Width-10, stringSize.Height);
// Draw string to screen.
e.Graphics.DrawString(
measureString,
stringFont,
Brushes.Black,
new PointF(0, 0));



If I deduct about 10 from the stringSize.Width like shown in the above code, the gap dissappears and the result is perfect.

Since 10 is an arbitary value and when used with lager fonts the message is intersected by the right border of the rectagle, I am having problems

What is going on? Am I missing something. I have used the same font for both while measuring and drawing the message.

You might say why do you worry about this. This is a minor thing. But what I have is an ArrayList of messages. But when these messages are drawn there appears to have gaps which I don't like. I am using this to code a custom control of mine which supports scrolling. So I need this measurement to be very precise.

Please help.Any suggestions would be appreciated much

jmcilhinney
September 6th, 2005, 06:41 PM
I can't really help exactly, but I've had issues with MeasureString and I have heard of many others too. Basically, it seems to be unrelaible. At least your not alone, for what it's worth. If it would work in your situation, rather than using GDI, you could try using a Label and setting its Width to equal its PreferredWidth.

Norfy
September 7th, 2005, 03:19 AM
Just done a quick google search on your problem and it would appear to be a common one.

Solutions either revolve around passing a StringFormat.GenericTypographic into the MeasureString method or using Graphics.MeasureCharacterRanges instead.

darwen
September 7th, 2005, 05:13 AM
Oh, fonts are fun aren't they ?

Firstly :

MeasureString seems to do the measure using Graphics.TextRenderingHint=TextRenderingHint.SingleBitPerPixel or TextRenderingHint.AntiAlias.

I.e. without hinting.

Set your text rendering hint to either of the above and you'll see that the text fits the box much better.

Now, you can use GetCharacterRanges : however, this ignores any overlapping ascenders or descenders on characters. To see this try doing a Times New Roman italic lowercase F. If you do FFFFF then you'll see that the tails of each F overlap the previous character. GetCharacterRanges ignores this overlap at the start and end of the string.

Personally I've never found a nice way around this problem. I have to render bitmaps pixel-perfect (i.e. the bounds I have is 100% accurate) and the only way I've found to do this reliably is to draw the text into a larger box, get the bitmap bits and find the left & right hand sides manually by testing the alpha channel.

Darwen.