Reputation: 13
If the searched word is at the beginning or end of the line of, I want to color it. If it's in the middle of the line not colorful. I tried many thing but it's not working right.
Seems like beginning of the line is working. But end of the first line only can color. I want to color for all lines end. I think i need index of each line's beggining and loop but i can't do it.
How can i fix it?
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;
}
Upvotes: 1
Views: 717
Reputation: 32223
I suggest to change your code a little bit. You'll notice why when the RichTextBox text length grows.
Asking for the Lines[]
content is not exactly a good thing, much worse in a loop, when you access this Property probably many of times.
You can see in the .Net Source Code what happens (each time - the Lines
Property values are not cached and cannot be).
GetLineFromCharIndex()
and GetFirstCharIndexFromLine()
use instead SendMessage
to send the EM_LINEFROMCHAR
and EM_LINEINDEX
messages to the Edit control - which uses cached values - and are pretty fast.
Regex.Matches()
to collect the indexes of the matched word(s) (you can use more than one word, separated by a pipe: "|"
, but here we handle just one word. When matching more than one word, use a List<Match>
and the Match.Length
instead of searchWord.Length
) and extract just the Index position of each match. IndexOf("\n", [StartPosition])
, using the first line index (which is also used for the selection) as the starting position. The RichTextBox Control uses only \n
as line separator, so we don't need to worry about \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;
}
}
Edit: Since Regex.Matches
is not allowed, you can use IndexOf()
in a loop:
var indexes = new List<int>();
int wordPosition = -1;
do {
if ((wordPosition = txt.IndexOf(searchWord, wordPosition + 1)) >= 0) {
indexes.Add(wordPosition);
}
} while (wordPosition >= 0);
Upvotes: 0
Reputation: 301
Try:
int newLineIndex = i + 1 < richTextBox1.Lines.Length ? richTextBox1.GetFirstCharIndexFromLine(i + 1) - 1 : richTextBox1.TextLength;
Upvotes: 1