Более быстрый способ закрасить все вхождения в RichTextBox в C#
У меня есть RichTextBox, и есть около 1000 вхождений указанной строки поиска.
Я использую следующую функцию, чтобы закрасить все вхождения:
public void ColorAll(string s)
{
rtbxContent.BeginUpdate();
int start = 0, current = 0;
RichTextBoxFinds options = RichTextBoxFinds.MatchCase;
start = rtbxContent.Find(s, start, options);
while (start >= 0)
{
rtbxContent.SelectionStart = start;
rtbxContent.SelectionLength = s.Length;
rtbxContent.SelectionColor = Color.Red;
rtbxContent.SelectionBackColor = Color.Yellow;
current = start + s.Length;
if (current < rtbxContent.TextLength)
start = rtbxContent.Find(s, current, options);
else
break;
}
rtbxContent.EndUpdate();
}
Но я обнаружил, что это очень медленно.
Тем не менее, если я закрашиваю все вхождения другого слова, которое содержит меньше вхождений в одном и том же тексте, я обнаружил, что это очень быстро.
Так что я думаю, что медлительность от (эти две строки могут включать обновление интерфейса):
rtbxContent.SelectionColor = Color.Red;
rtbxContent.SelectionBackColor = Color.Yellow;
Есть ли более быстрый способ выполнения той же работы, например, я делаю раскраску в памяти, а затем отображаю результат за один раз?
Я проясняю себя?
Благодарю.
4 ответа
Есть более быстрый способ.
Используйте регулярные выражения, чтобы найти совпадения, затем выделите в поле richtextbox
if (this.tBoxFind.Text.Length > 0)
{
try
{
this.richTBox.SuspendLayout();
this.Cursor = Cursors.WaitCursor;
string s = this.richTBox.Text;
System.Text.RegularExpressions.MatchCollection mColl = System.Text.RegularExpressions.Regex.Matches(s, this.tBoxFind.Text);
foreach (System.Text.RegularExpressions.Match g in mColl)
{
this.richTBox.SelectionColor = Color.White;
this.richTBox.SelectionBackColor = Color.Blue;
this.richTBox.Select(g.Index, g.Length);
}
}
finally
{
this.richTBox.ResumeLayout();
this.Cursor = Cursors.Default;
}
}
Количество времени, которое требуется, прямо пропорционально количеству происшествий.
Это, вероятно, находка, которая использует больше всего времени. Вы можете заменить эту строку:
start = rtbxContent.Find(s, start + s.Length, options);
с этим:
start = rtbxContent.Find(s, current, options);
Так как вы вычислили ток равным start + s.Length
Вы также можете хранить переменную s.Length, поэтому вам не нужно каждый раз считать все символы в строке. То же самое касается rtbxContent.TextLength.
Поиск строки является линейным. Если ты найдешь Find
Способ медленный, может быть, вы можете использовать сторонний инструмент для поиска вас. Все, что вам нужно, это индекс шаблона в строке.
Может быть, это поможет вам. Вы должны рассчитать разницу и использовать более быстрый.
Вы на правильном пути, в чем виновата медленная реализация Winforms RichTextBox. Вы также преуспели в использовании методов BeginUpdate и EndUpdate (я полагаю, вы взяли их отсюда?). Но, увы, этого недостаточно.
Пара решений:
1: попробуйте записать RTF прямо в текстовое поле. Это довольно грязный, сложный формат, но, к счастью, я создал ответ, который поможет.
2: Этот высоко оцененный внешний проект также выглядит достойным внимания: http://www.codeproject.com/Articles/161871/Fast-Colored-TextBox-for-syntax-highlighting