In a C# forms app, how can I search for highlighted text in a RichTextBox, like that available in Microsoft Word using the ‘Find and Replace’ format option.
There does not appear to be a field in the RichTextBoxFinds Enum that has this option. If I search for what I want to do on Google, I can find plenty of examples of how to search for text and highlight it, but nothing to find text that is highlighted. I also cannot find anything relating to this subject on the Stack Overflow site.
I am seeking suggestions on methods I could potentially use to do this, or ways to approach the problem.
Update
I have now created the below code in response to feedback to search for highlighted text (SelectionBackColour not white) in a RichTextBox which works but appears dreadfully slow compared to using Find to search for a string. I can speed things up if I set the HideSelection property to true before I start the loop, but still to slow, and when it enters the loop, the RichTextBox just turns dark grey until the loop is exited and I set HideSelection false again. What could be limiting the speed?
private bool FindNextH(int hightLightColour, int selectionStart, int selectionEnd)
{
int matchColour = hightLightColour;
bool matchHighlight = true;
if (matchColour == -1) // White
{
matchHighlight = false;
}
int state = 0;
int highlightStart = 0;
int highlightLength = 0;
int highlight = -1;
bool found = false;
richTextBox1.SelectionStart = selectionStart;
richTextBox1.SelectionLength = 1;
for (int i = selectionStart; i <= selectionEnd; i++)
{
richTextBox1.SelectionStart = i;
int colour = richTextBox1.SelectionBackColor.ToArgb();
switch (state)
{
case 0:
if (colour != -1)
{
if (matchHighlight)
{
if (colour == matchColour)
{
state = 1;
highlightStart = i;
highlight = colour;
}
}
else
{
state = 1;
highlightStart = i;
highlight = colour;
}
}
break;
case 1:
if ((colour != highlight) || (i == selectionEnd))
{
highlightLength = i - highlightStart;
richTextBox1.SelectionStart = highlightStart;
richTextBox1.SelectionLength = highlightLength;
textBox2.Text = richTextBox1.SelectedText;
found = true;
}
break;
default:
break;
}
if (found)
{
break;
}
}
return found;
}
Further testing has been done to quantify timings as follows:
Rich Text File containing 30,093 words, 137,984 characters (no spaces), 167,844 characters with spaces. ‘TestWord’ is contained in the file just over halfway through and is highlighted green.
Using Microsoft Word’s ‘Find and Replace’ (Ctrl H), with ‘Format’ set to ‘Highlight’ and the ‘Find what’ blank, it takes approximately one second for the document to scroll to the found highlighted word, starting with the cursor at the first character. If I use ‘Find and Replace’ to search for the text, no formatting, then it takes about the same time.
If I run a test using ‘richTextBox1.Find’ to search for ‘TestWord’, it takes between 5 and 15 ms to execute, and the text in the richTextBox1 jumps to it instantaneously, so very quick.
If I run a test using my function ‘FindNextH()’, it takes approximately 3.8 seconds to find the highlighted text, if I set ‘richTextBox1.HideSelection’ to ‘true’ before calling the function, and returning it to ‘false’ afterwards. During the 3.8 seconds, the richTextBox1 window goes dark gey and the text disappears, returning only when the highlighted word has been found.
If ‘richTextBox1.HideSelection’ is set to ‘false’ before calling ‘FindNextH(), it takes approximately 50 seconds to find the highlighted word, during which time you can the cursor scrolling through the text.
What can I do to speed this up? Clearly Microsoft have cracked it in MS Word. It is a pity that this feature is not a part of the ‘Find’ method.
Code that calls the two search functions below for reference:
richTextBox1.HideSelection = false;
stopWatch.Start();
int IndexOfSearchResultFound = richTextBox1.Find(_SearchKeyword, _KeywordSelectionStart, _KeywordSelectionEnd,
RichTextBoxFinds.None | RichTextBoxFinds.WholeWord | RichTextBoxFinds.MatchCase);
stopWatch.Stop();
richTextBox1.HideSelection = false;
TimeSpan timeDelay = stopWatch.Elapsed;
richTextBox1.HideSelection = true;
stopWatch.Start();
found = FindNextH(colour, selectionStart, selectionEnd);
stopWatch.Stop();
richTextBox1.HideSelection = false;
TimeSpan timeDelay = stopWatch.Elapsed;