c++c++buildervcltrichedit

How to organize a search in the text and highlight the found elements in TRichEdit in C++Builder?


I have a problem. It is necessary to organize a search in the text and highlight the found elements. I can't figure out why the problem is that the branch "comes off" or something like that. C++ program, C++Builder environment.

I used ChatGPT, but it don't help me. I can't figure out why the problem is that the branch "comes off" or something like that.

Here's my code (it doesn't work correctly):

void __fastcall TForm1::btnSearchClick(TObject* Sender)
{
  String searchTextStr = SearchText->Text;
  String allText = RichEditText->Text;
  RichEditText->SelStart = 0;
  RichEditText->SelLength = allText.Length();
  RichEditText->SelAttributes->Color = clWindowText;

  int foundPos = allText.Pos(searchTextStr);
  int searchOffset = 0;

  while (foundPos > 0) {
    RichEditText->SelStart = searchOffset + foundPos - 1;
    RichEditText->SelLength = searchTextStr.Length();
    RichEditText->SelAttributes->Color = clRed;

    searchOffset += foundPos;
    allText = allText.SubString(foundPos + searchTextStr.Length(), allText.Length() - foundPos - searchTextStr.Length() + 1);
    foundPos = allText.Pos(searchTextStr);
  }
}

This is my problem:

image


Solution

  • You are not taking into account that line breaks used inside the RichEdit may be different than the line breaks that the Text property returns. That affects the offsets you can use with the SelStart property. They need to be actual character offsets within the RichEdit's internal text.

    Also, you are not adjusting the searchOffset and allText correctly after each search result is found.

    This fixed code works for me:

    void __fastcall TForm1::btnSearchClick(TObject* Sender)
    {
      String searchTextStr = SearchText->Text;
      String allText = AdjustLineBreaks(RichEditText->Text, tlbsLF);
      RichEditText->SelStart = 0;
      RichEditText->SelLength = allText.Length();
      RichEditText->SelAttributes->Color = clWindowText;
    
      int foundPos = allText.Pos(searchTextStr);
      int searchOffset = 0;
    
      while (foundPos > 0) {
        RichEditText->SelStart = searchOffset + foundPos - 1;
        RichEditText->SelLength = searchTextStr.Length();
        RichEditText->SelAttributes->Color = clRed;
    
        searchOffset += (foundPos + searchTextStr.Length());
        allText = allText.Delete(1, foundPos + searchTextStr.Length());
        foundPos = allText.Pos(searchTextStr);
      }
    }
    

    image

    That being said, you really should use the TRichEdit::FindText() method instead. There is no need to touch the RichEdit's Text property at all, eg:

    void __fastcall TForm1::btnSearchClick(TObject* Sender)
    {
      String searchTextStr = SearchText->Text;
      int allTextLen = RichEditText->GetTextLen();
    
      RichEditText->SelStart = 0;
      RichEditText->SelLength = allTextLen;
      RichEditText->SelAttributes->Color = clWindowText;
    
      TSearchTypes options;
      int foundPos = RichEditText->FindText(searchTextStr, 0, allTextLen, options);
    
      while (foundPos >= 0) {
        RichEditText->SelStart = foundPos;
        RichEditText->SelLength = searchTextStr.Length();
        RichEditText->SelAttributes->Color = clRed;
    
        foundPos += searchTextStr.Length();
        foundPos = RichEditText->FindText(searchTextStr, foundPos, allTextLen-foundPos, options);
      }
    }