首先,回答问题How to measure width of character precisely?
,对这种情况并没有什么帮助,所以这不是的重复。
我有一个字符串。我使用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)
答案 0 :(得分:8)
你只需要消除额外的宽度。您可以使用string format:
执行此操作GdipStringFormatGetGenericTypographic()
你也可以使用:
float doubleWidth = g.MeasureString(text+text,...).Width;
float singleWidth = g.MeasureString(text).Width;
float textWidth = doubleWidth-singleWidth;
这将允许您使用其他语言,如日语。
On 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);
}
答案 1 :(得分:4)
我在这里参加派对有点晚了,但是我试图做类似的事情,偶然发现了这个问题。你可能已经从the documentation for the Graphics.MeasureString
method on MSDN看到了以下评论:
MeasureString方法设计用于单个字符串,并在字符串之前和之后包含少量额外空格以允许悬垂字形。此外,DrawString方法调整字形点以优化显示质量,并且可能显示比MeasureString报告的字符串更窄的字符串。要获取适合布局中相邻字符串的度量标准(例如,在实现格式化文本时),请使用MeasureCharacterRanges方法或采用MeasureString的StringFormat方法之一,并传递{{ 3}}。另外,请确保GenericTypographic的TextRenderingHint为Graphics。
您似乎正在尝试遵循此建议,因为您使用StringFormat.GenericTypographic
作为自定义StringFormat
对象的起点。但是,行
format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
有效地否定了您从StringFormat.GenericTypographic
开始的事实,因为它清除了之前设置的任何标志。您可能要做的是设置StringFormatFlags.MeasureTrailingSpaces
标志,同时保留其他标志,如下所示:
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
答案 2 :(得分:1)
尝试使用此方法:
GDI+ (graphics.MeasureString and graphics.DrawString) >> System.Drawing.Graphics
GDI (TextRenderer.MeasureText and TextRenderer.DrawText)
它也可以帮助您:
编写自定义度量方法:
- 在特殊字符上拆分条目字符串
- 使用上述.net方法
- 计算特殊字符的宽度和总和......
答案 3 :(得分:0)
使用Graphics.MeasureCharacterRanges返回包含所有单个字母的所有矩形的方法,其位置在此处给出:Measure character positions 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;
}
}
请注意,矩形的高度是字体的高度,而不是字符本身的高度。如果您需要身高,请检查以下信息:Determining exact glyph height in specified font
最后一点:我使用MeasureCharacterRanges的原因是因为我尝试的所有其他方法都未能给我一个边界框,文本的左右两边都没有空格。这篇The wonders of text rendering and GDI帖子提供了一种方法来获取字符串宽度并使用TextRenderer删除此空间,因此整个过程可以用大约两行代码完成。我还没有检查结果。