Я не сомневаюсь, что читатель уже довольно хорошо разбирается в VCL, чтобы самостоятельно освоить общие принципы применения TRichEdit. Как мне кажется, использование свойств SelStart, SelLength, SelText для выделения и изменения текста достаточно интуитивно, также как и изменение атрибутов этого текста с помощью свойства SelAttributes. На мой взгляд, достаточно интересным примером использования послужило бы описание стандартных функций поиска и замены, благо в TRichEdit есть соответствующий метод FindText. Форму делаем, например такую:
Впрочем, подпись формы можно и полаконичнее :)). В RichEdit я кое-что впечатал, видимо, фантазии не хватает :( но для пробного поиска и замена как раз сойдет. Главное меню никаких субпунктов не содержит, поэтому и обработчики такие. Листинг:
#include <stdio.h>//чтоб sprintf работал //--------------------------------------------------------------------------- void __fastcall TForm2::Find1Click(TObject *Sender) { Find->FindText = RichEdit1->SelText; Find->Execute(); } //--------------------------------------------------------------------------- void __fastcall TForm2::Replace1Click(TObject *Sender) { Replace->FindText = RichEdit1->SelText; Replace->Execute(); } //--------------------------------------------------------------------------- void __fastcall TForm2::FindFind(TObject *Sender) { if((Sender!=Find)&&(Sender!=Replace))return; TFindDialog* f = (TFindDialog*)Sender; //комментарий. Дело в том, что TReplaceDialog //является потомком TFindDialog, поэтому это преобразование сработает в любом случае //будь это TFindDialog или TReplaceDialog TSearchTypes st; //Опции, введенные пользователем if(f->Options.Contains(frMatchCase))st<<stMatchCase; if(f->Options.Contains(frWholeWord))st<<stWholeWord; if(RichEdit1->SelLength)RichEdit1->SelStart++; //Когда программа находит что-то, она подсвечивает текст. //Если HideSelection==true и фокус лежит не на основной форме, //то выделение видно не будет RichEdit1->HideSelection = false; int Found = RichEdit1->FindText(f->FindText,RichEdit1->SelStart, RichEdit1->Text.Length(),st); if(Found!=-1) { RichEdit1->SelStart = Found; //Прокрутить окно ввода до выделенного места. //С таким же успехом здесь мог быть метод Perform. SendMessage(RichEdit1->Handle,EM_SCROLLCARET,0,0); RichEdit1->SelLength = f->FindText.Length(); } else { Application->MessageBox("Searching has reached the end of the document", "Search",MB_OK); f->CloseDialog(); }; //SetFocus(); //эта инструкция пригодилась бы, //если бы не был установлен флаг HideSelection } //--------------------------------------------------------------------------- void __fastcall TForm2::ReplaceReplace(TObject *Sender) { FindFind(Sender); if(RichEdit1->SelLength==0)return; char buf[64]; sprintf(buf,"Replace this occurence of \"%s\"?",Replace->FindText.c_str()); if(Application->MessageBox(buf,"Replace",MB_YESNO)==IDYES) RichEdit1->SelText = Replace->ReplaceText; if(Replace->Options.Contains(frReplaceAll)) ReplaceReplace(Sender); //Здесь рекурсивное обращение к функции. //Возможно не самый лучший вариант, поскольку //при появлении ошибки в алгоритме вылетит исключение //Stack overflow, но зато самый краткий. } //---------------------------------------------------------------------------
Можно использовать при создании очередного текстового редактора. Логика в общем-то всегда одинаковая, с небольшими отличиями. Правда, не предусмотрено направление поиска, но это всегда можно реализовать. Проект можно загрузить.