尝试获取 C# 中的字符串宽度来模拟自动换行和文本位置(现在用 richTextBox 编写)。
richTextBox 的大小是 555x454 px,我使用等宽字体 Courier New 12pt。
I tried 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;
}