TextRenderer.MeasureText and Graphics.MeasureString mismatch in size
TextRenderer
uses GDI to render the text, whereas Graphics
uses GDI+. The two use a slightly different method for laying out text so the sizes are different.
Which one you should use depends on what will eventually be used to actually draw the text. If you are drawing it with GDI+ Graphics.DrawString
, measure using Graphics.MeasureString
. If you are drawing using GDI TextRenderer.DrawText
, measure using TextRenderer.MeasureText
.
If the text will be displayed inside a Windows Forms control, it uses TextRenderer
if UseCompatibleTextRendering
is set to false
(which is the default).
Reading between the lines of your question, you seem to be using TextRenderer
because you don't have a Graphics
instance outside the Paint
event. If that's the case, you can create one yourself to do the measuring:
using( Graphics g = someControl.CreateGraphics() )
{
SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}
If you don't have access to a control to create the graphics instance you can use this to create one for the screen, which works fine for measurement purposes.
using( Graphics g = Graphics.FromHwnd(IntPtr.Zero) )
{
SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}
Unable to get correct Size of DrawnText using TextRenderer
instead of using TextRenderer use GraphicsPath:
var path = new GraphicsPath();
path.AddString(text, font.FontFamily, (int)font.Style, size, new Point(0, 0), StringFormat.GenericTypographic);
var area = Rectangle.Round(path.GetBounds());
Here is sample code that generates image with size of text:
private Image DrawText(String text, Font font, int size, Color textColor, Color backColor)
{
var path = new GraphicsPath();
path.AddString(text, font.FontFamily, (int)font.Style, size, new Point(0, 0), StringFormat.GenericTypographic);
var area = Rectangle.Round(path.GetBounds());
Rectangle br = Rectangle.Round(path.GetBounds());
var img = new Bitmap(br.Width, br.Height);
var drawing = Graphics.FromImage(img);
drawing.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
drawing.SmoothingMode = SmoothingMode.HighSpeed;
drawing.Clear(backColor);
drawing.TranslateTransform((img.Width - br.Width) / 2 - br.X, (img.Height - br.Height) / 2 - br.Y);
drawing.FillPath(Brushes.Black, path);
Brush textBrush = new SolidBrush(textColor);
drawing.Save();
textBrush.Dispose();
drawing.Dispose();
return img;
}
Here are sample results:
problem with TextRenderer.MeasureText
MeasureText is not known to be accurate.
Heres a better way :
protected int _MeasureDisplayStringWidth ( Graphics graphics, string text, Font font )
{
if ( text == "" )
return 0;
StringFormat format = new StringFormat ( StringFormat.GenericDefault );
RectangleF rect = new RectangleF ( 0, 0, 1000, 1000 );
CharacterRange[] ranges = { new CharacterRange ( 0, text.Length ) };
Region[] regions = new Region[1];
format.SetMeasurableCharacterRanges ( ranges );
format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
regions = graphics.MeasureCharacterRanges ( text, font, rect, format );
rect = regions[0].GetBounds ( graphics );
return (int)( rect.Right );
}
How to correctly measure characters in string using TextRenderer?
You should use MeasureString from the graphics object. Also take a look at TextRenderer.MeasureText and Graphics.MeasureString mismatch in size. It will explain the difference.
Adapt the height of a TextBox
TextBox.GetPositionFromCharIndex returns the pixel position of a character. Position here means top/left so we need to add one more line..
This seems to work here:
textBox.Height = textBox.GetPositionFromCharIndex(textBox4.Text.Length - 1).Y + lineHeight;
I get the line height like this:
int lineHeight = -1;
using (TextBox t = new TextBox() { Font = textBox.Font }) lineHeight = t.Height;
I set the Height
instead of the ClientSize.Height
, which is slightly wrong unless BorderStyle
is None
. You can change to textBox.ClientSize = new Size(textBox.ClientSize.Width, l + lh);
Related Topics
How Abstraction and Encapsulation Differ
Why Are C# Interface Methods Not Declared Abstract or Virtual
How to Convert Ienumerable to Observablecollection
Convert String to Nullable Type (Int, Double, etc...)
How to Get the Index of an Item in a List in a Single Step
Performance of Static Methods VS Instance Methods
Can a Unit Test Project Load the Target Application's App.Config File
What's the Difference Between Application.Run() and Form.Showdialog()
How to Get the Time Difference Between Two Datetime Objects Using C#
How to Discover the "Path" of an Embedded Resource
How to Write Asynchronous Linq Query
Get File Name from Uri String in C#
Getting the "Diff" Between Two Arrays in C#
Linq Expression to Return Property Value
How to Do Network Discovery Using Udp Broadcast
Exclude Property on Update in Entity Framework