尝试在C#中获取字符串宽度以模拟wordwrap和文本的位置(现在写在richTextBox中)。计算字符串宽度的奇怪行为(以像素为单位)以模拟文字换行
richTextBox的大小是555x454像素,我使用等宽字体Courier New 12pt。
我试过TextRenderer.MeasureText()
和Graphics.MeasureString()
方法。
TextRenderer
返回的值大于Graphics
所以文本通常适合一行,我的代码确定应该包装到其他行。
但是在使用Graphics
时,另一方面,我的代码确定特定的字符串比在原始richTextBox中打印时短,因此它被包装到错误位置的下一行。
在调试过程中,我发现计算宽度不同,这很奇怪,因为我使用等宽字体,因此所有字符的宽度应该相同。但我从Graphics.MeasureString()
得到类似的东西(例如:'' - 5.33333254,'S' - 15.2239571,'\ r' - 5.328125)。
我怎样才能用C#精确计算字符串宽度,如此模拟自动换行并确定像素中的特定文本位置?
为什么在使用等宽字体时宽度在不同字符中会有所不同?
注意:我正在开展个人眼动追踪项目,并且我想确定在实验过程中放置了哪些特定的文本片段,以便我可以告诉用户正在查找哪些字词。例如。在时间t
用户正在寻找点[256,350] PX,我知道在这个地方有方法WriteLine
的调用。 我的目标视觉刺激是源代码,带有缩进,制表符,行结尾,放置在一些可编辑的文本区域(将来可能是一些简单的在线源代码编辑器)。
这里是我的代码:
//before method call
var font = new Font("Courier New", 12, GraphicsUnit.Point);
var graphics = this.CreateGraphics();
var wrapped = sourceCode.WordWrap(font, 555, graphics);
public static List<string> WordWrap(this string sourceCode, Font font, int width, Graphics g)
{
var wrappedText = new List<string>(); // output
var actualLine = new StringBuilder();
var actualWidth = 0.0f; // temp var for computing actual string length
var lines = Regex.Split(sourceCode, @"(?<=\r\n)"); // split input to lines and maintain line ending \r\n where they are
string[] wordsOfLine;
foreach (var line in lines)
{
wordsOfLine = Regex.Split(line, @"(|\t)").Where(s => !s.Equals("")).ToArray(); // split line by tabs and spaces and maintain delimiters separately
foreach (string word in wordsOfLine)
{
var wordWidth = g.MeasureString(word, font).Width; // compute width of word
if (actualWidth + wordWidth > width) // if actual line width is grather than width of text area
{
wrappedText.Add(actualLine.ToString()); // add line to list
actualLine.Clear(); // clear StringBuilder
actualWidth = 0; // zero actual line width
}
actualLine.Append(word); // add word to actual line
actualWidth += wordWidth; // add word width to actual line width
}
if (actualLine.Length > 0) // if there is something in actual line add it to list
{
wrappedText.Add(actualLine.ToString());
}
actualLine.Clear(); // clear vars
actualWidth = 0;
}
return wrappedText;
}
这是相当困难的。 RichTextBox仅用于测试目的。而且我保持分离。将有一个应用程序(可能是一些在线源代码编辑器 - 但现在只是简单的RichTextBox)和另一个分离的应用程序,它将处理在第一个应用程序中收集的离线数据。 – Gondil
是的,我知道这很复杂,但就我所理解的最终目标而言,“所以我可以告诉用户看哪些单词”。在网页上,由于不同的屏幕分辨率,不同的浏览器,不同的缩放设置等等,计算文本大小和模拟文字换行的方法会变得更加复杂。这就是为什么我认为通过使用屏幕上的某个点来获取文本更为容易。对于网络这种方法在这里讨论:http://stackoverflow.com/questions/2444430/how-to-get-a-word-under-cursor-using-javascript – Pasick