2011-09-09 144 views
2

我想在我的文本框的子类80个字符画保证金。这里是我的代码:为什么TextRenderer.MeasureText在这里不准确?

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):

但与其他字体,这原来是轻微不准确的。这里是索拉的截图在12号,例如:

正如你可以看到,线切割线穿过0,当改为它应该是的0

权编辑:

我忘了提,“保证金”是WinForms.Label。

+0

猜猜你将有不同的'TextFormatFlags'玩。 – leppie

+0

首先要排除的是它是常数还是乘法。如果将它设置为40,它是否与相同数量的结束字符重叠?如果是这样,那么显然'LeftMargin'需要一些调整。 –

+0

达明:如果我说'margin.Left = charWidth + LEFTMARGIN;',我也有同样的问题:宋体是好的,但索拉不是。 – Tom

回答

2

好的,我解决了这个问题。我不得不通过发送EM_GETMARGINS(而不仅仅是假设左边距为2,它适用于只是某些字体/大小)来获得文本框的左边距,和我有这个base.OnFontChanged(e);做我OnFontChanged覆盖。谢谢,所有的帮助。

0

我想尝试只需设置Width

Width = charWidth * 80 + LeftMargin; 

我从会自动调整大小基于文本的宽度TextBox创建一个派生类。它与你所提到的两种字体:

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

+1

什么宽度?我不能只设置文本框的宽度,因为我正在创建右边距,如截图所示。 – Tom

+0

所以你想要一个大小相等的左右边距?也许你想要的屏幕截图会有所帮助 – SwDevMan81

+0

我只想要一个右边距。 “LeftMargin”是TextBox的自然左边距。现在我已经在10号包含了Courier New的截图,它展示了应该看起来如何。 – Tom

1

使用Graphics.MeasureString代替。结果是SizeF,而不是像TextRenderer方法返回的Size

+0

如果我使用“SizeF size = graphics.MeasureString(new string('m',80),Font);”,我得到同样的问题(Courier New与Consolas不同) – Tom

+0

IIRC,你需要一些特定的StringFormat设置。将寻找我写回来处理这个问题的代码。 – leppie

+0

谢谢。我现在似乎已经解决了这个问题,正如我对这个问题的回答中所提到的。 – Tom

1

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

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

     margin.Left = stringWidth; 
+0

Courier New和Consolas *是固定宽度的字体,所以此评论不回答问题。 – Tom

+0

ClientSize和TextFormatFlags.NoPadding是这里的关键参数,没有它们 - 测量不起作用。谢谢! –