У меня проблема. Необходимо организовать поиск по тексту и выделить найденные элементы. Не могу понять, почему проблема в том, что ветка "отлетает" или что-то в этом роде. Программа C++, среда C++Builder.
Я использовал
Вот мой код (он работает неправильно):
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);
}
}
Это моя проблема:
Извините, я вас не понимаю... Где я должен поменять этот код?
Вы говорите по-украински?
Замените searchOffset += foundPos;
на searchOffset += foundPos + searchTextStr.Length();
Есть ли причина, по которой вы не используете метод TRichEdit::FindText()?
Я не использовал метод TRichEdit::FindText(), поскольку не знал о его существовании.
Ой, неужели сейчас 2024 год, а не 2004 год?
Вы не учитываете, что разрывы строк, используемые внутри RichEdit, могут отличаться от разрывов строк, возвращаемых свойством Text
. Это влияет на смещения, которые вы можете использовать со свойством SelStart
. Они должны быть реальными смещениями символов во внутреннем тексте RichEdit.
Кроме того, вы неправильно настраиваете searchOffset
и allText
после каждого результата поиска.
Этот фиксированный код работает для меня:
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);
}
}
При этом вам действительно следует использовать вместо этого метод TRichEdit::FindText(). Нет необходимости вообще трогать свойство Text
RichEdit, например:
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);
}
}
searchOffset += foundPos + searchTextStr.Length();
, ведь именно столько ты отрубишь в началеallText