Finding text in a Rich Text Box Control

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.




Answer this question

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);

    else

    pos = 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 term

    rtbDocument.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 pos

    sLastSearch = ""; //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 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
    {
    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

    This worked well, thank you, but I wanted to highlight the string that is found. I'm assuming that's what's saposed to be happening when you say "rtbDocument.Select(...)", but it's not showing up on mine. I also tried setting selectionStart and selectionlength property, to no avail.

    Thanks in Advance.

  • UnWiNd

    So obvious...Thanks

  • 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

    Nope, that still hasn't solved the problem, but it still works. I'll try and figure it out.

  • 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);

    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

    {

    //this is a good idea, but put it first

    //it simply looks better to the user this way

    rtbDocument.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

    could be that the rtb needs its .HideSelection property setting to false.

  • Finding text in a Rich Text Box Control