文本编辑器,就是捕获键盘事件,获得输入字符,在控件表面绘制字符串,设定光标位置。这一系列的文章,将告诉大家所有这些操作该如何处理,有什么注意点。这篇随笔将首先要讨论一个看似很简单,其实有很多注意点的小问题,如何获得字符串的长度(这个问题在处理光标位置,绘制被选中区域的时候,将起到决定性的作用)。
要知道字符串的长度,可能大家一下子想到的是Graphics的MeasureString,只要指定了字体和字符串后,用这个方法就能获得一个矩形的区域,这个区域是Graphics对象用DrawString方法在空间表面绘制字符串时所要的区域。这个区域的宽度不就是我们想知道的字符串的宽度吗?
开始的时候,我也是这么想的,但是使用后立刻发现MeasureString有很多问题。当然,其中有些问题我是对这个方法理解不足造成的,有的问题确实是MeasureString无能为力的。(如果哪位大侠知道解决方法,吼一下啊)
1.尾部空格的问题。
如果你使用MeasureString去测量两个字符串,一个在尾部有空格,一个在尾部没有空格,你将会发现,这两个字符串测量出来的宽度是一样的。例如“TextEditor” 和 “TextEditor ”的宽度是一样的。(全角和半角空格的命运一样,都被忽略不计了)。这个问题,其实是我对MeasureString方法理解不足造成的,其实MeasureString的最后一个StringFormat标志位是可以设定是不是要忽略尾部空格的。
StringFormat标志位 | 说明 |
MeasureTrailingSpaces | 包括每一行结尾处的尾随空格。在默认情况下,MeasureString 方法返回的边框都将排除每一行结尾处的空格。设置此标记以便在测定时将空格包括进去。 |
当我解决这个问题的时候,当时有点小小的高兴,以为求字符串的宽度的问题就到这里为止了。其实真正的噩梦才刚刚开始。
2.为什么用MeasureString测量出来的字符宽度,都不实际宽度稍微大一点啊?
使用MeasureString测量出来的字符宽度,总是比实际宽度大一些,而且随着字符的长度增大,貌似实际宽度和测量宽度的差距也越来越大了。查了一下MSDN,找到了下面这个理由:
MeasureString 方法旨在与个别字符串一起使用,它在字符串前后包括少量额外的空格供突出的标志符号使用。
可能当时MS这样设计的出发点是好的,但是却不是我想要的方法。(光标的位置必须精确的在字符的后面)在Google上找了半天,终于找到了一个代替MeasureString的方法:
TextRenderer.MeasureText(注意:此方法在 .NET Framework 2.0 版中是新增的。)
Dim dc As IDeviceContext Dim text As String Dim font As Font Dim proposedSize As Size Dim flags As TextFormatFlags Dim returnValue As Size returnValue = TextRenderer.MeasureText(dc, text, font, proposedSize, flags)
参数
- dc
-
测量文本所使用的设备上下文。
- text
-
要测量的文本。
- font
-
要应用于已测量文本的 Font。
- proposedSize
-
初始边框的 Size。
- flags
-
要应用于已测量文本的格式说明。
返回值
使用指定的 font 和格式绘制的 text 的 Size(以像素为单位)。这个方法,要达到我需要的效果,需要注意设定2个地方:
完成后的方法大概是这个样子的,输入参数是字符串,返回一个矩形区域。矩形区域的宽度就是字符串的精确宽度了。
'MeasureText:将边框设定为0,TextFormatFlags:NoPadding 不在边框中添加空白边距
Return TextRenderer.MeasureText(Me.CreateGraphics, strText, mCodeFont, _
End Function
以前一直以为要测量字符串的长度,只要用MeasureString就可以了,现在看来,MeasureString还是有部分局限性的,也可能是我孤陋寡闻,不知道如何正确使用MeasureString方法。MeasureString不去真正使用,光看文档,是不可能真正领会,真正了解这个方法的。纸上得来终觉浅,绝知此事需恭行,大概就是这个意思吧。