在RichTextBox的TextChange事件上计算日文文本长度时的性能问题
本文关键字:文本 问题 性能 文文本 事件 TextChange RichTextBox 计算 | 更新日期: 2023-09-27 17:55:03
我用c# 2.0编写了自定义的richtextbox。用户将在此文本框中输入日语文本。当用户键入超过300的文本时,它会用黄色突出显示多余的字符。日语文本可以包含半宽字符和全宽字符,我想把半宽字符的大小定为"0.5",全宽字符的大小定为"1"。
下面是我的代码…
Dictionary<int, float> charSizes = new Dictionary<int, float>();
void HighlightingTextBox_TextChanged(object sender, EventArgs e)
{
int index = this.SelectionStart;
// Reset highlighting and font.
HighlightText(0, this.BackColor, true);
// Highlight Text
float charCount = 0;
int highlightIndex = 0;
string currentText = this.Text;
for (int k = 0; k < currentText.Length; k++)
{
int c = currentText[k];
if (charCount <= CharacterLimit)
{
if (charSizes.ContainsKey(c)) // Use already calculated Size
charCount = charCount + charSizes[c];
else
{
// Check if character is Half width or Full Width
string charString = currentText[k].ToString();
string fullChar = Microsoft.VisualBasic.Strings.StrConv(charString, Microsoft.VisualBasic.VbStrConv.Wide, 1041);
if (c == (int)fullChar[0])
{
// Ascci value matches after converting to full width. So its Full width char.
charCount++;
charSizes[c] = 1;
}
else
{
charCount = charCount + 0.5f;
charSizes[c] = 0.5f;
}
}
highlightIndex++;
}
// Enforce "Arial" font for English characters in Japanese text
this.Select(k, 1);
this.SelectionFont = (c < 128) ? new Font("Arial", 9.5f) : this.Font;
this.SelectionLength = 0;
}
if (charCount > CharacterLimit)
HighlightText(highlightIndex, HighlightColor, false);
this.SelectionStart = index;
}
private void HighlightText(int selectionStart, Color highlightColor, bool enforceFont)
{
this.Select(selectionStart, this.Text.Length);
this.SelectionBackColor = highlightColor;
if (enforceFont)
this.SelectionFont = this.Font;
this.SelectionLength = 0;
}
有什么问题?
此代码适用于前8到10个字符。但在那之后,它的工作速度很慢(花了很多时间,因为它要遍历文本的"每个"字符)。如果用户键入速度快,则需要几秒钟才能在UI上出现新字符。
在这种情况下如何提高性能?还有其他的计算方法吗?
在这种例程中获得性能的最简单方法是:只计算发生了什么变化。
只需比较新旧文本,查看添加或删除了哪些字符,并根据它们修改总数。
你永远不会一次计算多于一个。
——另外,缓存你的Arial 9.5字体,而不是每次都创建一个新的字体。
为了最大限度地减少处理对用户输入的干扰-仅在他们暂停设置的间隔时更新它。
private Timer _timer = new System.Windows.Forms.Timer();
private bool _processingText;
public MyRichTextBox()
{
_timer = new Timer();
_timer.Interval = 1000;
_timer.Tick += new EventHandler(ProcessText);
}
protected override void OnTextChanged(EventArgs e)
{
if (_processingText == false)
{
_timer.Stop();
_timer.Start();
}
}
private void ProcessText(object sender, EventArgs e)
{
_processingText = true;
_timer.Stop();
// Insert your processing logic here
_processingText = false;
}