I have two strings, in Times New Roman that are being measured by Graphics.MeasureString(). Viewing the strings in Word shows one string longer than the other, but MeasureString returns a smaller number for the longer string.
Here is the code:
class Program
{
public static System.Windows.Forms.Form form = new System.Windows.Forms.Form();
public static Graphics GRAPHIX = form.CreateGraphics();
static void Main(string[] args)
{
string text;
float total;
Font TIMES = new Font("Times New Roman", 8);
Font TIMES_BOLD = new Font("Times New Roman", 8, FontStyle.Bold);
Font TIMES_SMALL = new Font("Times New Roman", 6);
Font TIMES_ITALIC = new Font("Times New Roman", 8, FontStyle.Italic);
text = "Bedbugs bite(s) - see Injury, superficial, by site";
total = 0;
total += GRAPHIX.MeasureString("Bedbugs bite(s)", TIMES_BOLD).Width;
total += GRAPHIX.MeasureString(" - ", TIMES).Width;
total += GRAPHIX.MeasureString("see", TIMES_ITALIC).Width;
total += GRAPHIX.MeasureString(" ", TIMES).Width;
total += GRAPHIX.MeasureString("Injury, superficial, by site", TIMES).Width;
Console.WriteLine("{0}: {1}", text, total);
text = "Bloom (-Machacek) (-Torre) syndrome 757.39";
total = 0;
total += GRAPHIX.MeasureString("Bloom (-Machacek) (-Torre) syndrome", TIMES_BOLD).Width;
total += GRAPHIX.MeasureString(" ", TIMES).Width;
total += GRAPHIX.MeasureString("757.39", TIMES).Width;
Console.WriteLine("{0}: {1}", text, total);
Console.Read();
}
}
Here are the strings (Copy and paste in Word to confirm that the second is longer in Times New Roman):
Bedbugs bite(s) - see Injury, superficial, by site
You may use the overload of MeasureString that accepts StringFormat as parameter. I have here an example:
StringFormat sFormat = new StringFormat(StringFormat.GenericTypographic);
text = "Bedbugs bite(s) - see Injury, superficial, by site";
total = 0;
total += GRAPHIX.MeasureString("Bedbugs bite(s)", TIMES_BOLD, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString(" - ", TIMES, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString("see", TIMES_ITALIC, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString(" ", TIMES, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString("Injury, superficial, by site", TIMES, 500, sFormat).Width;
Console.WriteLine("{0}: {1}", text, total);
text = "Bloom (-Machacek) (-Torre) syndrome 757.39";
total = 0;
total += GRAPHIX.MeasureString("Bloom (-Machacek) (-Torre) syndrome", TIMES_BOLD, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString(" ", TIMES, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString("757.39", TIMES, Int32.MaxValue, sFormat).Width;
Console.WriteLine("{0}: {1}", text, total);
MSDN Remarks:
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.
Cheers,
Florin
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Thanks for the example. using GenericTypographic has given me the expected result for those strings. I have noticed another problem, though. Here are the two strings, shown in Word in Times 8pt:
and here is the code which produces the wrong result:
class Program
{
public static System.Windows.Forms.Form form = new System.Windows.Forms.Form();
public static Graphics GRAPHIX = form.CreateGraphics();
static void Main(string[] args)
{
string text;
float total;
Font TIMES = new Font("Times New Roman", 8);
Font TIMES_BOLD = new Font("Times New Roman", 8, FontStyle.Bold);
Font TIMES_SMALL = new Font("Times New Roman", 6);
Font TIMES_ITALIC = new Font("Times New Roman", 8, FontStyle.Italic);
StringFormat sFormat = new StringFormat(StringFormat.GenericTypographic);
text = "MCLS (mucocutaneous lymph node syndrome)";
total = 0;
total += GRAPHIX.MeasureString("MCLS", TIMES_BOLD, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString(" (mucocutaneous lymph node syndrome)", TIMES, Int32.MaxValue, sFormat).Width;
Console.WriteLine("{0}: {1}", text, total);
text = "Posttraumatic brain syndrome, nonpsychotic";
total = 0;
total += GRAPHIX.MeasureString("Posttraumatic brain syndrome, nonpsychotic", TIMES_BOLD, Int32.MaxValue, sFormat).Width;
Console.WriteLine("{0}: {1}", text, total);
Console.Read();
return;
}
}
I did add a second method mentioned in the MSDN: MeasureCharacterRanges, I did also follow the recommendation to set the TextRenderingHint to AntiAlias.
Here is the code to compare the results:
public static System.Windows.Forms.Form form = new System.Windows.Forms.Form();
public static Graphics GRAPHIX = form.CreateGraphics();
static void Main(string[] args)
{
string text;
float total;
Font TIMES = new Font("Times New Roman", 8);
Font TIMES_BOLD = new Font("Times New Roman", 8, FontStyle.Bold);
Font TIMES_SMALL = new Font("Times New Roman", 6);
Font TIMES_ITALIC = new Font("Times New Roman", 8, FontStyle.Italic);
GRAPHIX.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
Console.WriteLine();
StringFormat sFormat = new StringFormat(StringFormat.GenericTypographic);
//sFormat.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.LineLimit | StringFormatFlags.FitBlackBox | StringFormatFlags.MeasureTrailingSpaces;
text = "Bedbugs bite(s) - see Injury, superficial, by site";
total = 0;
total += GRAPHIX.MeasureString("Bedbugs bite(s)", TIMES_BOLD, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString(" - ", TIMES, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString("see", TIMES_ITALIC, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString(" ", TIMES, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString("Injury, superficial, by site", TIMES, 500, sFormat).Width;
Console.WriteLine("{0}: {1}", text, total);
total = 0;
total += MeasureDisplayStringWidth(GRAPHIX, "Bedbugs bite(s)", TIMES_BOLD, sFormat);
total += MeasureDisplayStringWidth(GRAPHIX, " - ", TIMES, sFormat);
total += MeasureDisplayStringWidth(GRAPHIX, "see", TIMES_ITALIC, sFormat);
total += MeasureDisplayStringWidth(GRAPHIX, " ", TIMES, sFormat);
total += MeasureDisplayStringWidth(GRAPHIX, "Injury, superficial, by site", TIMES, sFormat);
Console.WriteLine("{0}: {1}*", text, total);
text = "Bloom (-Machacek) (-Torre) syndrome 757.39";
total = 0;
total += GRAPHIX.MeasureString("Bloom (-Machacek) (-Torre) syndrome", TIMES_BOLD, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString(" ", TIMES, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString("757.39", TIMES, Int32.MaxValue, sFormat).Width;
Console.WriteLine("{0}: {1}", text, total);
total = 0;
total += MeasureDisplayStringWidth(GRAPHIX, "Bloom (-Machacek) (-Torre) syndrome", TIMES_BOLD, sFormat);
total += MeasureDisplayStringWidth(GRAPHIX, " ", TIMES, sFormat);
total += MeasureDisplayStringWidth(GRAPHIX, "757.39", TIMES, sFormat);
Console.WriteLine("{0}: {1}*", text, total);
text = "MCLS (mucocutaneous lymph node syndrome)";
total = 0;
total += GRAPHIX.MeasureString("MCLS", TIMES_BOLD, Int32.MaxValue, sFormat).Width;
total += GRAPHIX.MeasureString(" (mucocutaneous lymph node syndrome)", TIMES, Int32.MaxValue, sFormat).Width;
Console.WriteLine("{0}: {1}", text, total);
total = 0;
total += MeasureDisplayStringWidth(GRAPHIX, "MCLS", TIMES_BOLD, sFormat);
total += MeasureDisplayStringWidth(GRAPHIX, " (mucocutaneous lymph node syndrome)", TIMES, sFormat);
Console.WriteLine("{0}: {1}*", text, total);
text = "Posttraumatic brain syndrome, nonpsychotic";
total = 0;
total += GRAPHIX.MeasureString("Posttraumatic brain syndrome, nonpsychotic", TIMES_BOLD, Int32.MaxValue, sFormat).Width;
Console.WriteLine("{0}: {1}", text, total);
total = 0;
total += MeasureDisplayStringWidth(GRAPHIX, "Posttraumatic brain syndrome, nonpsychotic", TIMES_BOLD, sFormat);
Console.WriteLine("{0}: {1}*", text, total);
Console.ReadLine();
}
static public float MeasureDisplayStringWidth(Graphics graphics, string text,
Font font, StringFormat sFormat)
{
StringFormat strFormat = new StringFormat(sFormat);
CharacterRange[] ranges;
Region[] charRegions;
float width = 0F;
for (int index = 0, i; index < text.Length; index += 32)
{
if (text.Length - index < 1) //if index becomes bigger then the text length
break;
else if (text.Length - index > 32) //if we're guarenteed 32 characters of bliss
ranges = new CharacterRange[32];
else //we got less then 32 characters, but atleast 1
ranges = new CharacterRange[text.Length - index];
//get the character ranges for the 32 char-length or less segment of text we're at
for (i = 0; i < ranges.Length; i++)
ranges[i] = new CharacterRange(index + i, 1);
//setup for measure
strFormat.SetMeasurableCharacterRanges(ranges);
System.Drawing.RectangleF rect = new System.Drawing.RectangleF(0, 0,
1000, 1000);
//measure it
charRegions = graphics.MeasureCharacterRanges(text, font, rect, strFormat);
//draw text one character at a time
for (i = 0; i < charRegions.Length; i++)
{
//draw the text
RectangleF bounds = charRegions[i].GetBounds(graphics);
width += bounds.Width;
}
}
return width;
}
I'm not sure how Word is drawing the texts. This is what you can do with GDI+. Most of the MeasureDisplayStringWidth code credit goes here:
Member
175 Points
61 Posts
Graphics.MeasureString inconsistency
Nov 11, 2010 09:58 AM|MattUCG|LINK
I have two strings, in Times New Roman that are being measured by Graphics.MeasureString(). Viewing the strings in Word shows one string longer than the other, but MeasureString returns a smaller number for the longer string.
Here is the code:
Here are the strings (Copy and paste in Word to confirm that the second is longer in Times New Roman):
Bedbugs bite(s) - see Injury, superficial, by site
Bloom (-Machacek) (-Torre) syndrome 757.39
measurestring graphics fonts
Contributor
2160 Points
496 Posts
Re: Graphics.MeasureString inconsistency
Nov 15, 2010 05:59 AM|florinlabou|LINK
Hi,
You may use the overload of MeasureString that accepts StringFormat as parameter. I have here an example:
MSDN Remarks:
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.
Cheers,
Florin
Member
175 Points
61 Posts
Re: Graphics.MeasureString inconsistency
Nov 15, 2010 09:23 AM|MattUCG|LINK
Thanks for the example. using GenericTypographic has given me the expected result for those strings. I have noticed another problem, though. Here are the two strings, shown in Word in Times 8pt:
and here is the code which produces the wrong result:
Contributor
2160 Points
496 Posts
Re: Graphics.MeasureString inconsistency
Nov 15, 2010 10:53 AM|florinlabou|LINK
I did add a second method mentioned in the MSDN: MeasureCharacterRanges, I did also follow the recommendation to set the TextRenderingHint to AntiAlias.
Here is the code to compare the results:
I'm not sure how Word is drawing the texts. This is what you can do with GDI+. Most of the MeasureDisplayStringWidth code credit goes here:
http://www.codeproject.com/KB/GDI-plus/drawing_text_strings.aspx
Florin