Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accuracy of TextRenderer.MeasureText results

Calling TextRenderer.MeasureText as follows:

TextRenderer.MeasureText(myControl.Text, myControl.Font);

and comparing the result to the size of the control to check if text fits. The results are sometimes incorrect. Have observed the following two issues:

  • Often when a Label is set to AutoSize, TextRenderer will report a width that is 1 pixel wider than the auto-sized width of the Control.
  • False negative where TextRenderer reports a width smaller than the control's but the text is still cut off. This occurred with "Estación de trabajo" -- not sure if the accent could somehow affect the width calculation?

Is there any way to improve the accuracy of the MeasureText method? Should I be calling one of the overrides that accepts a device context and/or format flags?

like image 609
Aidan Ryan Avatar asked Jul 06 '09 14:07

Aidan Ryan


4 Answers

I know it's probably no actual anymore. Yet for future readers here is a simple yet accurate method of measuring text in a control:

Graphics g=Graphics.FromHwnd(YOUR CONTROL HERE.Handle);
SizeF s=g.MeasureString("YOUR STRING HERE", Font, NULL, NULL, STRING LENGTH HERE, 1)
like image 74
anatolyArts Avatar answered Nov 13 '22 22:11

anatolyArts


Is there any way to improve the accuracy of the MeasureText method? Should I be calling one of the overrides that accepts a device context and/or format flags?

You have answered your question by yourself. Actually MeasureText based on Win32 DrawTextEx, and this function cannot work without valid device context. So when you call MeasureText override without hdc, it internally create desktop compatible hdc to do measurement.

Of course measurement depends on additional TextFormatFlags. Also keep in mind that Label painting (and measurement) depends on UseCompatibleTextRendering.

So general conclusion you should use MeasureText for your own code, for example when you then call DrawText with exactly same parameters, in all other cases size returned by MeasureText cannot be treated as precise.

If you need to get expected Label size, you should use GetPreferredSize method.

like image 21
arbiter Avatar answered Nov 13 '22 23:11

arbiter


Check out the TextFormatFlags parameter to this function:

TextRenderer::MeasureText(String, Font, Size, TextFormatFlags) 

http://msdn.microsoft.com/en-us/library/8wafk2kt.aspx

"The Size, in pixels, of text drawn on a single line with the specified font. You can manipulate how the text is drawn by using one of the DrawText overloads that takes a TextFormatFlags parameter. For example, the default behavior of the TextRenderer is to add padding to the bounding rectangle of the drawn text to accommodate overhanging glyphs. If you need to draw a line of text without these extra spaces you should use the versions of DrawText and MeasureText that take a Size and TextFormatFlags parameter. For an example, see MeasureText(IDeviceContext, String, Font, Size, TextFormatFlags)."

hth

like image 3
fusi Avatar answered Nov 13 '22 22:11

fusi


I don't know if I have a perfect solution but I ran into this when I was doing WinForms a few years back. The way I ended up compensating was by adjusting the returned measurement by a percentage. I cannot recall what I used (maybe 5% or 105?), but I do recall that I ended up using a constant percentage across the app and always rounded up.

like image 1
Jason Jackson Avatar answered Nov 13 '22 23:11

Jason Jackson