I find that when I use richTextBox.find(string) it only seems to search until the first occurrence of the string. How can I have a find like that in notepad etc. i.e. finds the next occurrence with each click.
The code I'm currently using to do this is:
int pos;
if (RichTextBox.SelectedText == "")
{
pos = RichTextBox.Find(searchTextBox.Text, 0, RichTextBoxFinds.None);
}
else
{
pos = RichTextBox.Find(searchTextBox.Text, (RichTextBox.SelectionStart + 1),
RichTextBoxFinds.None);}
if (pos < 0){
MessageBox.Show("Your query " + searchTextBox.Text + " could not be found", "Results", MessageBoxButtons.OK, MessageBoxIcon.Warning);RichTextBox.DeselectAll();
}
This seems to work, but not very well. I'm sure there must be a better way to do this. If you know how, please help!
Thanks in advance.

Finding text in a Rich Text Box Control
Dhiraj12345
I think that setting nLastPos default to -1 should work, so change:
private int nLastPos = 0; //store of position of last succesful search
//to
private int nLastPos = -1; //store of position of last succesful search
//--------------------------------------------------
if (nLastPos > 0 && sLastSearch == txtSearchTerm.Text)
//to
if (nLastPos > -1 && sLastSearch == txtSearchTerm.Text)
//--------------------------------------------------
nLastPos = 0; //clear last search pos
//to
nLastPos = -1; //clear last search pos
//That should work!
Thanks for all your help!
Tony Maresca
Thanks, it seems to have worked, however I have found that if the search term is at the very start of the document, it doesn't find the next occurrence i.e. if I have the text "Hello how are you today. Hello" and my search term is "Hello" only the first hello will be found. Any ideas
Apart from that it's excellent, thanks!
Tomas L
Hi Chuff,
I found another bug, if you have a long search term that finishes in the last word of the document and starts at the begginig the not found message never displays, also I put in the rtbDocument.Select() line to select the word, its not required, the find method will select the text already.
The modified code from my example now looks like this:
private
int nLastPos = 0; //store of position of last succesful search private string sLastSearch = ""; //the last string searched for succesfully private void butSearch_Click(object sender, System.EventArgs e){
int pos; //if the search term is the same as before we will continue our search //ie we have a previous succesful search if (nLastPos +1 > rtbDocument.Text.Length) nLastPos = 0; //the document length fix if (nLastPos > 0 && sLastSearch == txtSearchTerm.Text)pos = rtbDocument.Find(txtSearchTerm.Text, nLastPos + 1,
RichTextBoxFinds.None); elsepos = rtbDocument.Find(txtSearchTerm.Text, 0,
RichTextBoxFinds.None); if (pos < 0 || pos < nLastPos) //if pos < NlastPos one search term was found, this will be the same one{
//this prevents a bug that stops the messagebox showing after a very long search termrtbDocument.Select(0, 0);
//clear first else first selection is visible MessageBox.Show("Your query " + txtSearchTerm.Text + " could not be found", "Results", MessageBoxButtons.OK, MessageBoxIcon.Warning);nLastPos = 0;
//clear last search possLastSearch =
""; //clear last search string}
else{
sLastSearch = txtSearchTerm.Text;
//store the searcgh term //show the selection //this line is not required, find shows the selection anyway, //this was my mistake /*rtbDocument.Select(pos, sLastSearch.Length);*/ //we need to check we have not exceeded the length of the text in the rtb. //if we have not we are going to add the found search terms length to the start pos //this stops it sticking on the first word if it finds the term at pos 0 if (pos + txtSearchTerm.Text.Length < rtbDocument.Text.Length)nLastPos = pos + txtSearchTerm.Text.Length;
//store last search pos else nLastPos = pos;}
}
If that works for you I would use it, else just copy the parts that check the bounds, such as for long search terms, etc and place them into your code.
I found this link this morning: http://www.codeproject.com/cs/miscctrl/SearchableControls.asp
Regards
Baris ERGUN
This should resolve all the above issues:
private int nLastPos = 0; //store of position of last succesful searchprivate string sLastSearch = ""; //the last string searched for succesfully
private void butSearch_Click(object sender, System.EventArgs e)
{
int pos;
//if the search term is the same as before we will continue our search
//ie we have a previous succesful search
if (nLastPos > 0 && sLastSearch == txtSearchTerm.Text)
pos = rtbDocument.Find(txtSearchTerm.Text, nLastPos + 1, RichTextBoxFinds.None);
else
pos = rtbDocument.Find(txtSearchTerm.Text, 0, RichTextBoxFinds.None); if (pos < 0)
{
MessageBox.Show("Your query " + txtSearchTerm.Text + " could not be found", "Results", MessageBoxButtons.OK, MessageBoxIcon.Warning);
rtbDocument.Select(0, 0);
nLastPos = 0; //clear last search pos
sLastSearch = ""; //clear last search string
}
else
{
sLastSearch = txtSearchTerm.Text; //store the searcgh term
//show the selection
rtbDocument.Select(pos, sLastSearch.Length);
//we need to check we have not exceeded the length of the text in the rtb.
//if we have not we are going to add the found search terms length to the start pos
//this stops it sticking on the first word if it finds the term at pos 0
if (pos + txtSearchTerm.Text.Length < rtbDocument.Text.Length)
nLastPos = pos + txtSearchTerm.Text.Length; //store last search pos
else nLastPos = pos;
}
}
prk72
Thanks in Advance.
UnWiNd
glasgow1
Yet another problem:
I found that when using the code you just provided it would skip every second search term (I my term was only one letter, I forgot to test with a whole word, but this is still a problem)
My problem was when the RTB text was "aaaaa" and the search term was "a" it only found every second "a" i.e. found "aaaaa"
I have also updated my code and can no longer find any errors.
Try this and check it with the errors you have found:
private int nLastPos = -1;
private string sLastSearch = "";
private void butSearch_Click(object sender, EventArgs e)
{
int pos;
if (nLastPos > -1 && sLastSearch == txtSearchTerm.Text)
if (nLastPos > rtbDocument.Text.Length)
pos = rtbDocument.Find(txtSearchTerm.Text, 0, RichTextBoxFinds.None);
else
pos = rtbDocument.Find(txtSearchTerm.Text, nLastPos + sLastSearch.Length, RichTextBoxFinds.None);
else
pos = rtbDocument.Find(txtSearchTerm.Text, 0, RichTextBoxFinds.None);
if (pos < 0 || pos < nLastPos || pos == nLastPos)//This is the new bit, makes sure it is in a different place i.e not the same word
{
MessageBox.Show("Your query '" + txtSearchTerm.Text + "' could not be found", "Results", MessageBoxButtons.OK, MessageBoxIcon.Warning);
rtbDocument.Select(nLastPos, sLastSearch.Length); //This highlites the last term found when the search is over
nLastPos = -1;
sLastSearch = "";
}
else
{
nLastPos = pos;
sLastSearch = txtSearchTerm.Text;
//I also deleted the unnecessary code
}
}
Please test this code and tell me if you can find any bugs, thanks.
LabMan
Sorry to be a pest but have found yet another bug, if you type for example, "aaaaa", then search until the 4th a, then delete most of the a's, it will produce an error because it starts searching from beyond the end of the document. I have found a soloution to this problem, and also an alternate way of writing the code (I found this before reading the above). It seems to work, and fixes all the bugs exept if the only writing on your document is the search term, but in which case there's no need to be searching. The code I used was (I've highlighted my changes):
private int nLastPos = -1; //store of position of last succesful search, setting this default to -1 seems to fix the "first word" problem
private string sLastSearch = ""; //the last string searched for succesfully
private void butSearch_Click(object sender, System.EventArgs e)
{
int pos;
//if the search term is the same as before we will continue our search
//ie we have a previous succesful search
if (nLastPos > -1 && sLastSearch == txtSearchTerm.Text)
if (nLastPos > rtbDocument.Text.Length) //This if statement fixes the "longer than document" problem above
pos = rtbDocument.Find(txtSearchTerm.Text, 0, RichTextBoxFinds.None);
else
pos = rtbDocument.Find(txtSearchTerm.Text, nLastPos + sLastSearch.Length, RichTextBoxFinds.None);
pos = rtbDocument.Find(txtSearchTerm.Text, nLastPos + sLastSearch.Length, RichTextBoxFinds.None);
else
pos = rtbDocument.Find(txtSearchTerm.Text, 0, RichTextBoxFinds.None);
if (pos < 0 || pos < nLastPos) // "|| pos < nLastPos" fixes the problem where it goes back to the beginning
{
MessageBox.Show("Your query " + txtSearchTerm.Text + " could not be found", "Results", MessageBoxButtons.OK, MessageBoxIcon.Warning);
rtbDocument.Select(0, 0);
nLastPos = -1; //clear last search pos
sLastSearch = ""; //clear last search string
}
else
{
sLastSearch = txtSearchTerm.Text; //store the search term
nLastPos = pos;
rtbDocument.Select(pos, sLastSearch.Length); //show the selection
}
}
Which code do you think I should use PS Thanks for all your help!
Vipul211890
I've now found another problem where the message box does not appear, and it will continue to find from the beginning if the search term is located at the end of the text.
e.g. if the search term is "Hello" and the text being searched is "abc Hello Hello" It will just continually select the first hello, then the second, then the first, then the second...
Sorry about this... but has anyone got any ideas
jayakhanna
Hi Chuff,
This was tested in VS2003 but it should not to my knowledge make any difference in 2005.
private
int nLastPos = 0; //store of position of last succesful search private string sLastSearch = ""; //the last string searched for succesfully private void butSearch_Click(object sender, System.EventArgs e){
int pos;//if the search term is the same as before we will continue our search
//ie we have a previous succesful search if (nLastPos > 0 && sLastSearch == txtSearchTerm.Text)
pos = rtbDocument.Find(txtSearchTerm.Text, nLastPos + 1, RichTextBoxFinds.None);
else
pos = rtbDocument.Find(txtSearchTerm.Text, 0, RichTextBoxFinds.None); if (pos < 0)
{
MessageBox.Show("Your query " + txtSearchTerm.Text + " could not be found", "Results", MessageBoxButtons.OK, MessageBoxIcon.Warning);
rtbDocument.Select(0,0);
nLastPos = 0; //clear last search pos
sLastSearch = ""; //clear last search string
}
else
{
nLastPos = pos; //store last search pos
sLastSearch = txtSearchTerm.Text; //store the searcgh term //show the selection
rtbDocument.Select(pos,sLastSearch.Length);
}
}
Regards
Pramod S Kumar
anydobbo
Hi Chuff,
This has not been tested, but it looks like this should fix the bug:
change
if (nLastPos > 0 && sLastSearch == txtSearchTerm.Text)
pos = rtbDocument.Find(txtSearchTerm.Text, nLastPos + 1, RichTextBoxFinds.None);
else
pos = rtbDocument.Find(txtSearchTerm.Text, 0, RichTextBoxFinds.None);
to
if (nLastPos > 0 && sLastSearch == txtSearchTerm.Text)
pos = rtbDocument.Find(txtSearchTerm.Text, nLastPos + sLastSearch.Length, RichTextBoxFinds.None);
else
pos = rtbDocument.Find(txtSearchTerm.Text, 0, RichTextBoxFinds.None);
Regards
ahmedilyas
Looks good chuff, a couple of minor changes. (I really need to figure out a good way to format code on this forum)
private
int nLastPos = -1; private string sLastSearch = ""; private void butSearch_Click(object sender, EventArgs e){
int pos; if (nLastPos > -1 && sLastSearch == txtSearchTerm.Text) if (nLastPos > rtbDocument.Text.Length)pos = rtbDocument.Find(txtSearchTerm.Text, 0,
RichTextBoxFinds.None); else //GavH - the change is here (nLastPos +1)pos = rtbDocument.Find(txtSearchTerm.Text, nLastPos +1,
RichTextBoxFinds.None); elsepos = rtbDocument.Find(txtSearchTerm.Text, 0,
RichTextBoxFinds.None); if (pos < 0 || pos < nLastPos || pos == nLastPos)//This is the new bit, makes sure it is in a different place i.e not the same word{
//this is a good idea, but put it first //it simply looks better to the user this wayrtbDocument.Select(nLastPos, sLastSearch.Length);
//This highlites the last term found when the search is over MessageBox.Show("Your query '" + txtSearchTerm.Text + "' could not be found", "Results", MessageBoxButtons.OK, MessageBoxIcon.Warning);nLastPos = -1;
sLastSearch =
"";}
else{
nLastPos = pos;
sLastSearch = txtSearchTerm.Text;
//I also deleted the unnecessary code}
}
Chirag vm