Более быстрый способ закрасить все вхождения в 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

Другие вопросы по тегам