First of all, question How to measure width of character precisely?
which is answered, doesn't really help for this case, so this isn't a duplicate of that.
I have a string. I draw using graphics.DrawString
, however when I need to put another one after it, I need to know the precise width of previous string.
For this I use graphics.MeasureString with:
StringFormat format = new StringFormat(StringFormat.GenericTypographic);
format.Alignment = StringAlignment.Center;
format.Trimming = StringTrimming.None;
format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
I have tried many other functions, just as TextRendered.MeasureText
however all of them fail, with all possible combinations of parameters.
the mentioned combination of MeasureString is most close to what I need (it works in most cases, except for special characters), however using characters like # break it. The width is either shorter or longer.
Is there a way to get a precise size of text produced by DrawString function? How does the DrawString calculate the size of drawing area? It must be clearly some other function because the size always differ.
The source code of whole application is here https://gitorious.org/pidgeon/pidgeon-main/ (File where I work with this, is https://gitorious.org/pidgeon/pidgeon-main/blobs/master/scrollback/SBABox.cs)
You just need to eliminate extra width. You can do this by using string format:
GdipStringFormatGetGenericTypographic()
You could also use:
float doubleWidth = g.MeasureString(text+text,...).Width;
float singleWidth = g.MeasureString(text).Width;
float textWidth = doubleWidth-singleWidth;
This will allow you to work with other languages such as Japanese.
On codeproject, Pierre Anaud's solution was to use MeasureCharacterRanges
, which returns a region matching exactly the bounding box of the specified string:
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);
var ranges = 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);
}
I'm a little late to the party here, but I was trying to do something similar and stumbled on this question. You've probably already seen the following remark from the documentation for the Graphics.MeasureString
method on MSDN:
The MeasureString method is designed for use with individual strings and includes a small amount of extra space before and after the string to allow for overhanging glyphs. Also, the DrawString method adjusts glyph points to optimize display quality and might display a string narrower than reported by MeasureString. To obtain metrics suitable for adjacent strings in layout (for example, when implementing formatted text), use the MeasureCharacterRanges method or one of the MeasureString methods that takes a StringFormat, and pass GenericTypographic. Also, ensure the TextRenderingHint for the Graphics is AntiAlias.
It seems that you were trying to follow this advice because you're using StringFormat.GenericTypographic
as a starting point for your custom StringFormat
object. However, the line
format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
effectively negates the fact that you started with StringFormat.GenericTypographic
because it clears any previously set flags. What you probably meant to do is set the StringFormatFlags.MeasureTrailingSpaces
flag while preserving the other flags, like so:
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
Try to use this methods:
GDI+ (graphics.MeasureString and graphics.DrawString) >> System.Drawing.Graphics
GDI (TextRenderer.MeasureText and TextRenderer.DrawText)
It also may help you:
Write a custom measure method:
- Split entry string on special characters
- Use above .net methods
- Calculate width of special characters and sum ...
Read Ian Boyd answer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With