Peformance Issue when Calculating Japanese text length on TextChange event of RichTextBox
I have custom richtextbox written in C# 2.0. User will enter Japanese text in this textbox. While user typing if text size goes beyond 300, it highlights the extra characters by yellow color. Japanese text can contain half width and full width character and I want to count half width character as Size "0.5" and Full width character as size "1".
Following is my code...
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.Sel开发者_JAVA技巧ectionStart = 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;
}
What is the problem?
This code works ok for first 8 to 10 characters. But after that it works very slow (takes lot of time as it is going through "EACH" character of text). If user types fast, it takes few seconds to appear new characters on UI..
How to improve the performance in this case? Is there any other way for this calculation?
The simplest way to gain performance in this kind of routine: Only calculate what changed.
Just compare the old and new text, see what character(s) are added or removed, and modify the total based just on them.
You are never calculating more than one at a time this way.
-- Additionally, cache your Arial 9.5 font rather than creating a new one each time.
To minimize the processing interfering with user typing - only update it when they pause a set interval.
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;
}
精彩评论