7

首先,How to measure width of character precisely?已回答的问题对于这种情况并没有真正的帮助,所以这不是 that 的重复

我有一个字符串。我使用 绘制graphics.DrawString,但是当我需要在它之后放置另一个时,我需要知道前一个字符串的精确宽度。

为此,我使用 graphics.MeasureString 与:

StringFormat format = new StringFormat(StringFormat.GenericTypographic);
format.Alignment = StringAlignment.Center;
format.Trimming = StringTrimming.None;
format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;

我已经尝试了许多其他功能,TextRendered.MeasureText但是所有可能的参数组合都失败了。

上面提到的 MeasureString 组合最接近我需要的组合(它在大多数情况下都有效,特殊字符除外),但是使用 # 打破它之类的字符。宽度或短或长。

有没有办法获得 DrawString 函数产生的文本的精确大小?DrawString 如何计算绘图区域的大小?显然它必须是其他一些功能,因为大小总是不同的。

整个应用程序的源代码在这里https://gitorious.org/pidgeon/pidgeon-main/(我使用它的文件是https://gitorious.org/pidgeon/pidgeon-main/blobs/master/scrollback /SBABox.cs )

4

4 回答 4

9

你只需要消除额外的宽度。您可以使用字符串格式来做到这一点:

GdipStringFormatGetGenericTypographic()

您还可以使用:

float doubleWidth = g.MeasureString(text+text,...).Width;
float singleWidth = g.MeasureString(text).Width;
float textWidth = doubleWidth-singleWidth;

这将允许您使用其他语言,例如日语

在 codeproject 上,Pierre Anaud 的解决方案是使用MeasureCharacterRanges,它返回一个与指定字符串的边界框完全匹配的区域:

static public int MeasureDisplayStringWidth(Graphics graphics, string text, Font font)
{
    System.Drawing.StringFormat format  = new System.Drawing.StringFormat ();
    System.Drawing.RectangleF   rect    = new System.Drawing.RectangleF(0, 0, 1000, 1000);
    var ranges  = new System.Drawing.CharacterRange(0, text.Length);
    System.Drawing.Region[] regions = new System.Drawing.Region[1];

    format.SetMeasurableCharacterRanges (ranges);

    regions = graphics.MeasureCharacterRanges (text, font, rect, format);
    rect    = regions[0].GetBounds (graphics);

    return (int)(rect.Right + 1.0f);
}
于 2012-07-29T11:41:09.973 回答
6

我在这里参加聚会有点晚了,但我试图做类似的事情并偶然发现了这个问题。您可能已经从MSDN 上的方法文档中Graphics.MeasureString看到以下注释:

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

您似乎正在尝试遵循此建议,因为您将其用作自定义对象StringFormat.GenericTypographic的起点。StringFormat然而,线

format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;

有效地否定了您开始使用的事实,StringFormat.GenericTypographic因为它清除了任何先前设置的标志。您可能打算做的是设置StringFormatFlags.MeasureTrailingSpaces标志,同时保留其他标志,如下所示:

format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
于 2013-10-22T12:53:57.783 回答
1

尝试使用以下方法:

GDI+ (graphics.MeasureString and graphics.DrawString) >> System.Drawing.Graphics
GDI (TextRenderer.MeasureText and TextRenderer.DrawText)

它还可以帮助您:

编写自定义度量方法:

  • 在特殊字符上拆分条目字符串
  • 使用上述 .net 方法
  • 计算特殊字符的宽度并求和...

阅读伊恩博伊德的答案

于 2012-07-29T11:45:32.330 回答
0

此处给出了一种使用 Graphics.MeasureCharacterRanges 来返回包含字符串中每个单独字母的所有矩形及其位置的方法:Measure character Position when drawing long strings in C#

我已经使用了该帖子中的 MeasureCharactersInWord 和 MeasureCharacters 方法,然后为了找到确切的宽度而不在字符串的每一侧添加空格,我使用以下代码:

var w = 0F;
var rects = MeasureCharacters(Graphics.FromHwnd(IntPtr.Zero), font, text);
if (rects.Count>0)
{
    if (rects.Count == 1)
    {
        w = rects.First().Width;
    }
    else
    {
        var r0 = rects.First();
        var rN = rects.Last();
        w = rN.X - r0.X + rN.Width;
    }
}

请注意,矩形的高度是字体的高度,而不是字符本身的高度。如果您需要高度,请查看这篇文章:确定指定字体中的确切字形高度

最后一点:我使用 MeasureCharacterRanges 的原因是因为我尝试的所有其他方法都未能给我一个边界框,文本的左右两侧没有空间。这篇文章The wonders of text rendering and GDI提供了一种使用 TextRenderer 获取字符串宽度并删除此空间的方法,因此整个事情可以在大约两行代码中完成。虽然我还没有检查结果。

于 2018-06-26T15:24:55.160 回答