Why is TextRenderer.MeasureText inaccurate here?
I'm trying to draw a margin at 80 characters in my TextBox subclass. Here is my code:
class FooTextBox : TextBox
{
...
void UpdateMarginPosition()
{
using (Graphics graphics = CreateGraphics()) {
int charWidth = TextRenderer.MeasureText(graphics, "M", Font,
ClientSize, TextFormatFlags.NoPadding).Width;
const int LeftMargin = 2;
margin.Left = charWidth * 80 + LeftMargin;
}
}
}
This works fine for certain fonts 开发者_如何学Cat certain sizes (e.g., Courier New at size 10):
But with other fonts this turns out to be slightly inaccurate. Here is a screenshot with Consolas at size 12, for example:
As you can see, the line cuts through the 0, when instead it should be to the right of the 0.
EDIT:
I forgot to mention that 'margin' is a WinForms.Label.
Use Graphics.MeasureString
instead. The result is SizeF
and not Size
like the TextRenderer's method returns.
Okay, I solved the problem. I had to get the left margin of the TextBox by sending EM_GETMARGINS (rather than just assuming that the left margin is 2, which works for only some fonts/sizes), and I had to do this after base.OnFontChanged(e);
in my OnFontChanged override. Thanks, all, for the assistance.
But, you should use just fixed length font, because width of char 'I' is different than width of char 'M'. Or if you know string in textbox. You can change code:
int stringWidth = TextRenderer.MeasureText(graphics, this.text, Font,
ClientSize, TextFormatFlags.NoPadding).Width;
margin.Left = stringWidth;
I would try just setting the Width
Width = charWidth * 80 + LeftMargin;
I created a derived class from TextBox
that will auto size the width based on the Text. It works with both fonts you mentioned:
public class MyTextBox : TextBox
{
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
UpdateTextboxWidth();
}
}
void UpdateTextboxWidth()
{
using (Graphics graphics = CreateGraphics())
{
int text_width = TextRenderer.MeasureText(graphics, base.Text, Font,
ClientSize, TextFormatFlags.NoPadding).Width;
Width = text_width + Margin.Left + Margin.Right;
}
}
}
Note: In my project, the Margin.Left
and Margin.Right
are set to 3
精彩评论