碰到的问题:
我们的程序需要做文本的行数控制,也就是当文本输入至指定行数时,再增加行数就会出现警告,不能再进行输入了。
最初的解决方法:
因为RichTextBox本身带有Lines属性,所以开始的时候打算直接采用这个属性,然后在TextChanged事件中进行行数控制。但是实际运行时发现这种方法不行。
MSDN上对Lines属性的备注中有如下解释:
根据这个说明,如果用户一直输入文本,不主动输入回车符,则到控件最右边时控件会自动换行,但是它并不会把换行符后的文本被添加到该数组的一个新元素中,也就是说Lines属性的Count值不会变。如下图所示:
其实我想得到的值是4而不是1。
想到的解决方法1:
查阅MSDN,Graphic类中的MeasureString方法可以测量文本的行数,函数原型如下:
C#
public SizeF MeasureString(
string text,
Font font,
SizeF layoutArea,
StringFormat stringFormat,
out int charactersFitted,
out int linesFilled)
各个参数的意义可以查阅MSDN,最后一个参数的值就是我们想要的结果。
linesFilled
类型:System.Int32
字符串中的文本行数。
上图中的实际行数值就是用这种方法测量的。
这种方法实际运行时也有不准的时候,下图所示,原因如下(MeasureString的备注):
MeasureString 方法旨在与个别字符串一起使用,它在字符串前后包括少量额外的空格供突出的标志符号使用。另外,DrawString 方法会调整标志符号镑值以优化显示质量,它显示的字符串可能比 MeasureString 报告的窄。若要获得适合布局中相邻字符串的度量值(例如,实现格式化文本时),请使用 MeasureCharacterRanges 方法或者使用带有 StringFormat 的 MeasureString 方法中的一种,然后传递 GenericTypographic。同样,请确保 Graphics 的 TextRenderingHint 是 AntiAlias。
想到的解决方法2:
RichTextBox控件有GetCharIndexFromPosition函数,可以根据一个位置获取位置所在字符序号,可以伪造位置信息,从第一行开始计算位置所在的字符序号,判断是否是文本的最后一个字符,。不过这种方法在一行字符输入满,再输一个就自动换行后,得到的行数也不准确,不过还是比想到的解决方法1要准确些。
想到的解决方法3:
自己计算每个字符的宽度,然后计算换行,这种方法应该是最准确的 。