RichTextBox - Как выделить конец строки? - PullRequest
1 голос
/ 03 апреля 2020

Если искомое слово находится в начале или конце строки, я хочу его раскрасить. Если это в середине линии не красочный. Я перепробовал много вещей, но это не работает правильно.

Похоже, начало строки работает. Но конец первой строки только может раскрасить. Я хочу, чтобы цвет для всех строк заканчивается. Я думаю, что мне нужен индекс начала каждой строки и l oop, но я не могу это сделать.

My not working program

Как я могу это исправить?

 private void button1_Click(object sender, EventArgs e)
    {
        int wordLength = textBox1.Text.Length;
        string word = textBox1.Text;     
        for (int i = 0; i < richTextBox1.Lines.Count(); i++)
        {                
            int startIndex = richTextBox1.GetFirstCharIndexFromLine(i);
            richTextBox1.Find(word, startIndex, startIndex+wordLength, RichTextBoxFinds.None);
            richTextBox1.SelectionColor = Color.Red;
            richTextBox1.SelectionBackColor = Color.Yellow;

            int newLineIndex = richTextBox1.Lines[i].Length;
            richTextBox1.Find(textBox1.Text, (newLineIndex - wordLength), newLineIndex, RichTextBoxFinds.None);
            richTextBox1.SelectionColor = Color.Red;
            richTextBox1.SelectionBackColor = Color.Yellow;
        }         

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Попробуйте:

 int newLineIndex = i + 1 < richTextBox1.Lines.Length ? richTextBox1.GetFirstCharIndexFromLine(i + 1) - 1 : richTextBox1.TextLength;
0 голосов
/ 04 апреля 2020

Предлагаю немного изменить ваш код. Вы заметите, почему, когда длина текста RichTextBox увеличивается.
Запрашивать контент Lines[] - это не совсем хорошо, что гораздо хуже в oop, когда вы получаете доступ к этому свойству, вероятно, много раз.
В . Net Исходный код вы можете видеть, что происходит (каждый раз - значения Lines свойства не кэшируются и не могут быть).

GetLineFromCharIndex() и GetFirstCharIndexFromLine() используют вместо SendMessage отправку сообщений EM_LINEFROMCHAR и EM_LINEINDEX в элемент управления Edit - который использует кэшированные значения - и работают довольно быстро.

  • Используйте Regex.Matches(), чтобы собрать индексы совпадающих слов (вы можете использовать более одного слова, разделенных каналом: "|", но здесь мы обрабатываем только одно слово. При сопоставлении более чем одного слова используйте List<Match> и Match.Length вместо searchWord.Length) и извлекайте только позицию индекса каждого соответствия.
  • Затем l oop индексов и проверьте, соответствует ли текущая позиция индекса критериям.
  • Текущий конец строки находится с IndexOf("\n", [StartPosition]), используя индекс первой строки (который также используется для выбора) в качестве начальной позиции.

Элемент управления RichTextBox использует только \n в качестве разделителя строк, поэтому нам не нужно беспокоиться о \r.

string searchWord = "John";
var txt = richTextBox1.Text;
int textLenght = txt.Length;

// the indexes list can be created with the alternative method (using IndexOf() in a loop) 
var indexes = Regex.Matches(txt, searchWord, RegexOptions.Multiline)
                   .OfType<Match>()
                   .Select(m => m.Index).ToList();

foreach (int index in indexes) {
    int currentLine = richTextBox1.GetLineFromCharIndex(index);
    int lineFirstIndex = richTextBox1.GetFirstCharIndexFromLine(currentLine);
    int lineLastIndex = txt.IndexOf("\n", lineFirstIndex);

    if (index == lineFirstIndex ||
        index == lineLastIndex - searchWord.Length ||
        index == textLenght - searchWord.Length) {
        richTextBox1.Select(index, searchWord.Length);
        richTextBox1.SelectionColor = Color.Red;
    }
}

Редактировать : Поскольку Regex.Matches не разрешено , вы можете использовать IndexOf() в oop:

var indexes = new List<int>();
int wordPosition = -1;
do {
    if ((wordPosition = txt.IndexOf(searchWord, wordPosition + 1)) >= 0) {
        indexes.Add(wordPosition);
    }
} while (wordPosition >= 0);
...