2012-07-29 86 views
5

首先,问题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

可能重复([如何衡量字符串的像素宽度在.NET drawed超过Drawing.Bitmap?] http://stackoverflow.com/questions/2555739/how-to-measure-the-pixel-width-of-the-string-drawed-over-drawing-bitmap-in-net) – 2012-07-29 11:36:23

+0

如果问题没说清楚MeasureString不工作,这将是重复的 – Petr 2012-07-29 14:49:57

+0

没有怎样及何时“它不工作”更好的说明和代码,包括MeasureString和束带在一起,这恰恰是不是一个真正的问题。拿出一个小小的测试用具。 – 2012-07-29 16:12:00

回答

7

你只需要消除额外的宽度。您可以通过使用string format做到这一点:

GdipStringFormatGetGenericTypographic() 

您还可以使用:

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

这将让你与其他语言如日本工作。

On codeproject,皮埃尔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); 
} 
+0

它似乎工作,直到我发现了格式的一些问题,当我固定它,全功能刚开始返回相同错误的值MeasureString ... – Petr 2012-07-29 14:44:59

+1

工作得很好......唯一的解决方法就是行:**格式。 SetMeasrableCharacterRanges(new CharacterRange [] {ranges}); ** – ymz 2016-01-21 11:51:18

1

尝试使用此方法:

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

它也可能会帮助你:

写自定义测量方法:对特殊字符

  • 拆分进入串
  • 使用上面的.NET方法
  • 特殊字符和
  • 计算宽度...

Read Ian Boyd answer

2

我对这里的派对有点迟到,但我正在尝试做类似的事情,并且在这个问题上无法理解。你可能已经看到了以下的话从the documentation for the Graphics.MeasureString method on MSDN

MeasureString方法是专为个人使用的字符串,包括前和后弦的额外少量空间以允许悬垂字形。此外,DrawString方法调整字形点以优化显示质量,并且可能显示一个字符串窄于由MeasureString报道。以获得适合于相邻串中的布局的度量(例如,实施格式化文本时),则使用MeasureCharacterRanges方法或的MeasureString方法,需要一个一个StringFormat,并通过GenericTypographic。同时,确保TextRenderingHintGraphicsAntiAlias

您似乎在尝试遵循此建议,因为您使用的是StringFormat.GenericTypographic作为自定义StringFormat对象的起点。然而,该行

format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces; 

有效地否定了,你开始StringFormat.GenericTypographic,因为它会清除所有以前设置的标志的事实。你大概意思做的是设置StringFormatFlags.MeasureTrailingSpaces标志,同时保留其他标志,就像这样:

format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;