How to accurately measure line width?

First of all, the question How to measure width of character precisely? , to which the answer is given, does not really help in this case, therefore it is not a duplicate.

I have a line. I draw with graphics.DrawString , however, when I need to put another one after it, I need to know the exact width of the previous line.

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 tried many other functions, just like TextRendered.MeasureText however all of them fail, with all possible combinations of parameters.

the mentioned combination of MeasureString is closest 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 the exact size of the text created by the DrawString function? How does DrawString calculate the size of the drawing area? There must obviously be some other function, because the size is always different.

The source code of the entire application is here https://gitorious.org/pidgeon/pidgeon-main/ (The file where I work with this is https://gitorious.org/pidgeon/pidgeon-main/blobs/master/scrollback/SBABox. cs )

+5
c # winforms gdi +
source share
3 answers

You just need to eliminate the extra width. You can do this using the string format :

 GdipStringFormatGetGenericTypographic() 

You can 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.

In the code project, Pierre Anad's solution was to use MeasureCharacterRanges , which returns the area corresponding to the exact bounding box of the specified line:

 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); } 
+7
source share

I'm a little late to the party here, but I tried to do something similar and came across this question. You have probably already seen the following documentation note for the Graphics.MeasureString method on MSDN :

The MeasureString method is intended for use with individual lines and includes a small amount of extra space before and after the line, which allows overhanging glyphs. In addition, the DrawString method adjusts the glyph points to optimize display quality and can display a string already specified by MeasureString . To get metrics suitable for adjacent lines in the layout (for example, when formatting text), use the MeasureCharacterRanges method or one of the MeasureString , which takes a StringFormat and passes in GenericTypographic . Also, TextRenderingHint for Graphics AntiAlias.

It seems that you tried to follow this advice because you are using StringFormat.GenericTypographic as a starting point for your custom StringFormat object. However 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 wanted to do was set the StringFormatFlags.MeasureTrailingSpaces flag, while preserving other flags, for example:

 format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces; 
+2
source share

Try using the following methods:

 GDI+ (graphics.MeasureString and graphics.DrawString) >> System.Drawing.Graphics GDI (TextRenderer.MeasureText and TextRenderer.DrawText) 

It can also help you:

Write your own measurement method:

  • Split input string into special characters
  • Use the above .net methods
  • Calculate the width of special characters and sums ...

Read Jan Boyd's answer

+1
source share

All Articles