2

我开发了一个像 Word 这样的程序。为此,我需要将字符串写入同一“行”,并且我还希望能够以不同的方式格式化每个单词/字母/句子,控制颜色、大小、字体等。

所以我必须计算一个字符串的像素长度和高度,把它们排成一行。但是这个函数有一个问题(Graphics) MeasureString,这个函数在字符串的前面/后面放置了额外的长度。这个函数在空白方面也有一些问题。

我尝试了不同的 StringFormater,但每次它们返回的长度过长或不够。

是否存在用于在Graphics对象上写入不同格式字符串的函数或用于计算字符串的确切像素长度的函数?

4

2 回答 2

4

首先,要正确解决这是一个相当棘手的问题——您最好尝试找到一个现有的控件(例如RichTextBox)来为您解决这个问题。

也就是说,如果您确实想这样做,那么这或多或少是解决此问题的正确方法,但是如果您查看MeasureString 文档,您会注意到您看到的行为是故意的

MeasureString方法设计用于单个字符串,并在字符串前后包含少量额外空间,以允许悬垂字形。此外,DrawString方法会调整字形点以优化显示质量,并且可能会显示比MeasureString报告的更窄的字符串。要获得适合布局中相邻字符串的度量(例如,在实现格式化文本时),请使用MeasureCharacterRanges方法或采用StringFormat的 MeasureString 方法之一,并传递 GenericTypographic。此外,确保图形TextRenderingHintAntiAlias.

因此,在我看来,您应该改用Graphics.MeasureCharacterRanges 方法

这是我准备的示例,交易以两种不同的颜色呈现一些文本。要试用它,只需将其粘贴到新表单中

protected override void OnPaint(PaintEventArgs e)
{
    // This is where we wish to print our string
    var region = new RectangleF(50, 50, 200, 50);

    // This is the font we wish to use
    var font = new Font("Times New Roman", 16.0F);

    // Draw a string for comparison
    DrawString(e.Graphics, "RedBlack", font, Brushes.Black, new RectangleF(50, 150, 200, 50));

    // Draw the first string and keep a track of the Region it was rendered in
    var first = DrawString(e.Graphics, "Red", font, Brushes.Red, region);

    // Adjust the region we wish to print 
    region = new RectangleF(region.X + first.GetBounds(e.Graphics).Width, region.Y, region.Width, region.Height);

    // Draw the second string
    DrawString(e.Graphics, "Black", font, Brushes.Black, region);

    base.OnPaint(e);
}

private Region DrawString(Graphics g, string s, Font font, Brush brush, RectangleF layoutRectangle)
{
    var format = new StringFormat();
    format.SetMeasurableCharacterRanges(new[] { new CharacterRange(0, s.Length) });

    g.DrawString(s, font, brush, layoutRectangle, format);
    return g.MeasureCharacterRanges(s, font, layoutRectangle, format)[0];
}

这就是它的样子

表格截图

请注意,您需要小心剪辑 - 默认情况下,GDI 会为您将渲染的文本“换行”到新行,但是这将不再起作用,您最终会得到这样的结果

换行不正确的表单截图

此外,如果您尝试打印出具有不同字体/字体大小的文本,那么每种字体的“底部”都不会在您期望的位置排列。尝试查看Formatting text on a common baseline以获取有关如何处理该问题的一些提示。

于 2012-08-07T10:59:43.790 回答
0

MeasureString 无疑是解决这个问题的正确方法。看看这一边底部的示例http://msdn.microsoft.com/de-de/library/957webty(v=vs.80).aspx因为我会说没有其他方法。

于 2012-08-07T10:41:05.047 回答