C# 如何精确测量字符串的宽度?

C# 如何精确测量字符串的宽度?,c#,winforms,gdi+,C#,Winforms,Gdi+,首先,所回答的问题对这个案例并没有帮助,所以这不是重复的问题 我有一根绳子。我使用graphics.DrawString绘图,但是当我需要在它后面放置另一个时,我需要知道前一个字符串的精确宽度 为此,我使用graphics.MeasureString和: StringFormat format = new StringFormat(StringFormat.GenericTypographic); format.Alignment = StringAlignment.Center; format

首先,所回答的问题对这个案例并没有帮助,所以这不是重复的问题

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

为此,我使用graphics.MeasureString和:

StringFormat format = new StringFormat(StringFormat.GenericTypographic);
format.Alignment = StringAlignment.Center;
format.Trimming = StringTrimming.None;
format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
我尝试过许多其他函数,就像
TextRendered.MeasureText
一样,但是所有函数都失败了,并且有各种可能的参数组合

上面提到的度量值组合最接近我需要的(它在大多数情况下都有效,除了特殊字符),但是使用了像#break it这样的字符。宽度不是更短就是更长

有没有一种方法可以获得由DrawString函数生成的文本的精确大小?抽绳如何计算绘图区域的大小?它肯定是其他功能,因为大小总是不同的


整个应用程序的源代码在这里(我处理这个文件的地方是)

您只需要消除额外的宽度。您可以使用以下方法进行此操作:

您还可以使用:

float doubleWidth = g.MeasureString(text+text,...).Width;
float singleWidth = g.MeasureString(text).Width;
float textWidth = doubleWidth-singleWidth;
这将允许您使用其他语言,如日语

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

尝试使用以下方法:

GDI+ (graphics.MeasureString and graphics.DrawString) >> System.Drawing.Graphics
GDI (TextRenderer.MeasureText and TextRenderer.DrawText)
它也可以帮助您:

GDI+ (graphics.MeasureString and graphics.DrawString) >> System.Drawing.Graphics
GDI (TextRenderer.MeasureText and TextRenderer.DrawText)
编写自定义度量方法:

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

我来这里参加聚会有点晚了,但我正试图做一些类似的事情,却意外地发现了这个问题。您可能已经从中看到了以下评论:

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

似乎您正试图遵循此建议,因为您正在使用
StringFormat.genericypographic
作为自定义
StringFormat
对象的起点。但是,

format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
有效地否定了您从
StringFormat.genericypographic
开始的事实,因为它清除了以前设置的任何标志。您可能想做的是设置
StringFormatFlags.MeasureTrailingSpaces
标志,同时保留其他标志,如下所示:

format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;

使用Graphics.MeasureCharacterRanges返回字符串中包含每个字母的所有矩形及其位置的方法如下所示:

我使用了那篇文章中的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,是因为我尝试过的所有其他方法都未能为我提供一个文本左右没有空格的边界框。这篇文章给出了一种方法来获取字符串宽度,并使用TextRenderer删除这个空间,这样整个过程就可以在大约两行代码中完成。但我还没有检查结果。

如果问题没有明确说明度量值不起作用,可能会重复,如果没有更好地描述“它不起作用”的方式和时间,以及包含度量值和抽绳的代码,这就不是一个真正的问题。提出一个小的测试用例。它似乎可以工作,直到我发现一些格式问题,当我修复它时,整个函数开始返回与MeasureString相同的错误值…工作正常。。。唯一的修复方法是:format.setmeasureablecharacterranges(newcharacterrange[]{ranges});