- •Лекція №11
- •Системні діалоги
- •1. Загальна характеристика компонентів діалогів
- •2. Діалоги відкриття і збереження файлів — компоненти OpenDlalog, SaveDlalog, OpenPictureDialog, SavePictureDialog
- •3. Фрагменти діалогів — компоненти DriveComboBox, DirectoryListBox, FilterComboBox, FileListBox і cDirectoryOutline
- •Діалог вибору шрифту — компонент FontDialog
- •Діалоги вибору кольору — компоненти ColorDialog і ColorBox
- •Діалоги друку і установки принтера — компоненти PrintDialog і PrinterSetupDialog
- •Діалоги пошуку і заміни тексту — компоненти FindDialog і ReplaceDialog
-
Діалоги пошуку і заміни тексту — компоненти FindDialog і ReplaceDialog
Компоненти FindDialog і ReplaceDialog, що викликають діалоги пошуку і заміни фрагментів тексту, дуже схожі і мають однакові властивості, окрім однієї, яка задає замінюючий текст в компоненті ReplaceDialog. Така схожість не диво, оскільки ReplaceDialog — похідний клас від FindDialog.
Самі по собі компоненти FindDialog і ReplaceDialog не здійснюють ні пошуку, ні заміни. Вони тільки забезпечують інтерфейс з користувачем. А пошук і заміну треба здійснювати програмно. Для цього можна користуватися подією OnFind, що відбувається, коли користувач натиснув в діалозі кнопку Знайти далі, і подією OnReplace, що виникає, якщо користувач натиснув кнопку Замінити або Замінити все. У події OnReplace дізнатися, яку саме кнопку натиснув користувач, можна по значеннях прапорів frReplace і frReplaceAll.
Пошук заданого фрагмента в компоненті RichEdit легко проводити, використовуючи його метод FindText, оголошений таким чином:
int fastcall FindText(const System::AnsiString SearchStr,
int StartPos, int Length, TSearchTypes Options);
Цей метод шукає в тексті RichEdit фрагмент, заданий параметром SearchStr.
Пошук проводиться, починаючи з позиції StartPos (позиція першого символу тексту вважається нульовою), впродовж Length символів. Параметр Options є множиною, яка може містити елементи stWholeWord (пошук тільки цілого слова) і stMatchCase (пошук з урахуванням регістра). Метод повертає позицію знайденого входження. Якщо заданий фрагмент не знайдений, повертається -1.
Нижче приведений код, що здійснює пошук заданого фрагмента в тексті компоненту RichEdit1. Викликати діалог пошуку можна операторами:
/*початкове значення тексту пошуку - текст, виділений в RichEdit1*/
FindDialog1->FindText = RichEdit1->SelText;
FindDialogl->Execute();
Вони задають як початкове значення для пошуку текст, виділений у вікні RichEdit1, і потім викликають діалог пошуку FindDialog1.
Обробник події OnFind компоненту FindDialogl може мати вигляд:
void fastcall TForm1::FindDialog1Find(TObject *Sender)
{
int FoundAt, StartPos, ToEnd;
TSearchTypes Option;
//якщо текст було виділено, то пошук йде,
//починаючи з його останнього символу, інакше - з позиції курсору
StartPos = RichEdit1->SelStart;
if (RichEdit1->SelLength)
StartPos += RichEdit1->SelLength;
// ToEnd - довжина тексту, починаючи з першої позиції пошуку і до кінця
ToEnd = RichEdit1->Text.Length() - StartPos;
//пошук цілого слова чи ні залежно від параметрів користувача
if (FindDialog1->Options.Contains(frWholeWord))
Option << stWholeWord;
else Option >> stWholeWord;
//пошук з урахуванням або без урахування регістра залежно від
//параметрів користувача
if (FindDialog1->Options.Contains(frMatchCase))
Option << stMatchCase;
else Option >> stMatchCase;
FoundAt=RichEdit1->FindText(FindDialog1->FindText,StartPos,ToEnd,Option);
if (FoundAt != -1) // якщо знайдено
{
RichEdit1->SetFocus();
RichEdit1->SelStart = FoundAt;
RichEdit1->SelLength = FindDialog1->FindText.Length();
}
else ShowMessage("Текст ' " + FindDialog1->FindText + " 'не знайдений" ) ;
}
Функція FindDialog1Find спрацьовує, коли користувач натиснув в діалозі кнопку Знайти далі. Коментарі в тексті цієї функції пояснюють етапи пошуку. Спочатку проводиться установка області тексту (змінні StartPos і ToEnd), в якій проводиться пошук. Потім встановлюються атрибути пошуку — формується множина Option залежно від встановлених користувачем опцій. Потім методом FindText проводиться сам пошук. Якщо нового входження шуканого тексту не знайдено (метод FindText повернув -1), то користувачу видається повідомлення про це за допомогою функції ShowMessage.
Приведений приклад відносився до пошуку в компоненті RichEdit. Для організації пошуку в тексті компоненту Memo зручно використовувати метод Pos класу AnsiString, який оголошений таким чином:
int_fastcall Pos(const AnsiString & subStr) const;
Метод повертає індекс першого символу першого входження підрядка subStr в рядок, до якого застосовується цей метод. Індекси починаються з 1. Якщо subStr не міститься в рядку, то повертається 0.
Для організації пошуку буде потрібно ще дві функції класу AnsiString: Substring і LowerCase. Перша з них визначена як:
AnsiString_fastcall Substring(int index, int count) const;
Вона повертає підрядок, що починається з символу у позиції index і що містить count символів.
Функція LowerCase, визначена як
AnsiString_fastcall LowerCase()const;
повертає рядок символів S, переведений в нижній регістр.
Тепер ми можемо розглянути приклад організації пошуку. Хай у вашому застосуванні є компонент Memo1 і при виборі розділу меню MFind ви хочете організувати пошук в тексті, що міститься в Memo1. Для спрощення завдання виключимо опцію пошуку тільки цілих слів і опцію пошуку вгору від положення курсорe.
Програма, що реалізовує пошук, може мати наступний вигляд:
void_fastcall TForm1::MFindClick(TObject *Sender)
{
//початкове значення тексту пошуку - текст, виділений в Memo1
FindDialog1->FindText = Memo1->SelText;
FindDialog1->Execute();
}
void_fastcall TForm1::FindDialog1Find(TObject *Sender)
{
int FoundAt, StartPos, ToEnd;
//якщо було виділення, то пошук йде, починаючи з його останнього символу, інакше - з позиції курсору
StartPos = Memo1->SelStart;
if {Memo1->SelLength)
StartPos += Memo1->SelLength;
//ToEnd - довжина тексту, починаючи з першої позиції пошуку і до кінця
ToEnd = Memo1->Text.Length()- StartPos;
//пошук з урахуванням або без урахування регістра залежно від //параметрів користувача
if (FindDialog1->Options.Contains(frMatchCase))
FoundAt = StartPos + Memo1->Text.Substring(StartPos + 1,ToEnd) .Pos(FindDialog1->FindText);
else FoundAt = StartPos + Memo1->Text.Substring(StartPos+1, ToEnd) .LowerCase().Pos(FindDialogl->FindText.LowerCase());
if(FoundAt != StartPos) // якщо знайдено
{
Memo1->SetFocus();
Memo1->SelStart = FoundAt-1;
Memo1->SelLength = FindDialog1->FindText.Length();
}
else ShowMessage("Текст '" + FindDialog1->FindText + "' не знайдений");
}
Програма аналогічна до приведеної раніше для компоненту RiehEdit і відрізняється тільки декількома операторами, що здійснюють безпосередньо пошук.
Контрольні питання:
-
?
-
?
-
?
-
?
-
?
-
?