为什么TextRenderer.MeasureText在这里不准确?

时间:2011-09-09 11:47:23

标签: c# .net winforms

我正在尝试在TextBox子类中绘制80个字符的边距。这是我的代码:

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;
        }
    }
}

这适用于某些尺寸的某些字体(例如,大小为10的Courier New):

但是对于其他字体,这种结果有点不准确。以下是Consolas大小为12的屏幕截图,例如:

正如你所看到的,这条线穿过0,而它应该在0的右边。

编辑:

我忘了提到'margin'是WinForms.Label。

4 个答案:

答案 0 :(得分:2)

请改用Graphics.MeasureString。结果是SizeF而不是Size,就像TextRenderer的方法返回一样。

答案 1 :(得分:2)

好的,我解决了这个问题。我必须通过发送EM_GETMARGINS来获取TextBox的左边距(而不是假设左边距是2,仅适用于某些字体/大小),我必须在之后执行 { {1}}在我的OnFontChanged覆盖中。谢谢所有人的帮助。

答案 2 :(得分:1)

但是,你应该使用固定长度的字体,因为char'I'的宽度不同于char'M'的宽度。或者,如果您知道文本框中的字符串。您可以更改代码:

int stringWidth = TextRenderer.MeasureText(graphics, this.text, Font,
            ClientSize, TextFormatFlags.NoPadding).Width;

        margin.Left = stringWidth;

答案 3 :(得分:0)

我会尝试设置Width

Width = charWidth * 80 + LeftMargin;

我从TextBox创建了一个派生类,它将根据Text自动调整宽度。它适用于你提到的两种字体:

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;
      }
   }
}

注意:在我的项目中,Margin.LeftMargin.Right设置为3