字符串宽度测量方法不准确

时间:2012-12-13 22:29:02

标签: c# .net wpf string

我正在尝试调整RichTextBox.PageWidth的大小以限制为60个字符(固定宽度字体)。基本上我测量字符串然后我将PageWidth设置为测量的量。

当我使用它时,我的测量结果是2个字符。 (最后两个字符换行到下一行。)

任何人都知道如何为RichTextBox获取字符串的宽度而不将该文本实际放入RichTextBox

字符串度量方法(取自here):

private static double GetStringWidth(string text, 
                                     FontFamily fontFamily, 
                                     double fontSize)
{
    Typeface typeface = new Typeface(fontFamily, 
                                     FontStyles.Normal, 
                                     FontWeights.Normal, 
                                     FontStretches.Normal);

    GlyphTypeface glyphTypeface;
    if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
        throw new InvalidOperationException("No glyph typeface found");

    double size = fontSize;

    ushort[] glyphIndexes = new ushort[text.Length];
    double[] advanceWidths = new double[text.Length];

    double totalWidth = 0;

    for (int n = 0; n < text.Length; n++)
    {
        ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]];
        glyphIndexes[n] = glyphIndex;

        double width = glyphTypeface.AdvanceWidths[glyphIndex] * size;
        advanceWidths[n] = width;

        totalWidth += width;
    }

    return totalWidth;
}

使用上述方法:

var strToMeasure="012345678901234567890123456789012345678901234567890123456789";
richTextBox.FontFamily = new FontFamily("Courier New");
var fontFamily = richTextBox.FontFamily;
var fontSize = richTextBox.FontSize;

var measuredWidth = GetStringWidth(strToMeasure, fontFamily, fontSize);

richTextBox.Document.PageWidth = measuredWidth;
richTextBox.Document.MaxPageWidth = measuredWidth;
richTextBox.Document.MinPageWidth = measuredWidth;

更新
进一步的测试显示,它一直被2个字符关闭(4个字符或100个字符)。这让我相信RichTextBox正在填充内容。

2 个答案:

答案 0 :(得分:2)

RichTextBox可能会为了自己的布局目的消耗一些水平宽度,导致计算总是有点短。这个stackOverflow问题的答案可以帮助您解决问题。

Setting WPF RichTextBox width and height according to the size of a monospace font

答案 1 :(得分:1)

我使用这种方法,可能不是最好的,但它非常准确。

    private double MeasureText(string text, FontFamily font, double fontsize)
    {
        var mesureLabel = new TextBlock(); 
        mesureLabel.FontFamily = font;
        mesureLabel.FontSize = fontsize; 
        mesureLabel.Text = text; 
        mesureLabel.Padding = new Thickness(0); 
        mesureLabel.Margin = new Thickness(0); 
        mesureLabel.Width = double.NaN; 
        mesureLabel.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 
        mesureLabel.Arrange(new Rect(mesureLabel.DesiredSize));
        return mesureLabel.ActualWidth;
    }

用法:

 double length = MeasureText("hello", FontFamily, FontSize);