Лабораторная работа №7 Редактор текстов.
Шаг 1. Назвать форму TextEditor и сохранить проект под именем Editor. dpr. (Не забывайте устанавливать фирменную иконку для формы, а также название и иконку для приложения и, конечно, подсказки ко всем кнопкам.)
Шаг 2. Установить на форму компонент Panel1 и задайте его свойства (обязательно разобрать назначение этих и всех остальных свойств)
Align = alTop,
Caption = ‘’.
Шаг 3. Установить на форму компонент Memo1 и задайте его свойства
Align = alClient,
Lines = ‘’,
WordWrap = TRUE,
ScrolBars = ssBoth,
HideSelection = False (при переходе фокуса к другому компоненту не гасится выделение выделенного текста).
Шаг 4. Установить на форму компонент OpenDialog1 со следующими свойствами
DefaultExt = TXT,
Filter = Текстовые файлы | *.txt | Все файлы | *.*
Title = Открытие текстового файла,
Options (установить в TRUE)
ofHideReadOnly - из окна диалога удаляется выключатель “Открыть только для чтения”
ofFileMustExist - генерируется сообщение об ошибке, если выбран несуществующий файл,
ofNoReadOnlyReturn - генерируется сообщение об ошибке, если выбран файл типа ReadOnly.
Шаг 5. Установить на форму компонент SaveDialog1 со следующими свойствами
DefaultExt = TXT,
Filter = Текстовые файлы | *.txt | Все файлы | *.*
Title = Сохранение текстового файла,
Options (установить в TRUE)
ofHideReadOnly
ofNoReadOnlyReturn
ofOverwritePrompt - . генерируется сообщение об ошибке, если выбран уже существующий файл.
Шаг 6. Установить на панель кнопку с именем &Open и записать следующий обработчик события OnClick (текст обработчика проще не набирать, а просто скопировать через буфер; обязательно разберите смысл каждой команды)
With OpenDialog1 do
if Execute then begin
Memo1.Lines. LoadFromFile(FileName);
Caption:='TextEditor - '+ExtractFileName(FileName);
SaveDialog1.FileName:=FileName;
FileName:='';
end;
Шаг 7. Установить на панель кнопку с именем &Save и с обработкой события OnClick:
Memo1.Lines. SaveToFile(SaveDialog1.FileName);
Шаг 8. Установить на панель кнопку с именем Save&As и с обработкой события OnClick:
With SaveDialog1 do
if Execute then begin
Memo1.Lines. SaveToFile(FileName);
Caption:='TextEditor - '+ExtractFileName(FileName);
end;
Шаг 9. Установить на панель кнопку с именем E&xit и с обработкой события OnClick:
Close
Шаг 10. Поместить на форму компонент FontDialog1 с обработкой события OnApply:
Memo1.Font:=FontDialog1.Font
Шаг 11. Разместить на панели кнопку с именем &Font и с обработкой события OnClick:
With FontDialog1 do
if Execute then Memo1.Font:=Font
Шаг 12. Установить на форму компонент PrinterSetupDialog1.
Шаг 13. Установить на панель кнопку с именем Print Set&up и с обработкой события OnClick:
PrinterSetupDialog1.Execute
Шаг 14. Установить на форму компонент PrintDialog1
Шаг 15. Установить на панель кнопку с именем &Print и с обработкой события OnClick:
var FileOut : TextFile;
k : Integer;
begin
if PrintDialog1.Execute then begin
AssignPrn(FileOut);
Rewrite(FileOut);
Printer. Canvas. Font:=Memo1.Font;
for k:=0 to Memo1.Lines. Count-1 do
Writeln(FileOut, Memo1.Lines[k]);
CloseFile(FileOut)
end;
end;
Процедуры работы с принтером находятся в модуле Printers. Укажите его имя в списке uses раздела interface модуля Unit1.
Шаг 16. Поместить на панель кнопку с именем Fi&nd и с обработкой события OnClick:
FindDialog1.Execute
Шаг 17. Поместить на панель кнопку с именем &Replace и с обработкой события OnClick:
ReplaceDialog1.Execute
Шаг 18. Поместить на форму компоненты FindDialog1 и ReplaceDialog1 и установить в TRUE следующие общие свойства группы Options
frHideMachCase - прячет выключатель “С учетом регистра”,
frHideWholeWord - прячет выключатель “Только слово целиком”.
frHideUpDown - прячет кнопки выбора направления поиска.
Шаг 19. Определить обработчик события OnFind компонента FindDialog1;
Текст обработчика | Комментарий |
var Buff, FT, P : PChar; BuffLen : Integer; | Описание вспомогательных переменных. |
Begin With Sender as TfindDialog do begin | В начале процедуры указано, что используемые ниже свойства и методы будут относиться к объекту Sender (источник события), который рассматривается как объект класса TFindDialog. |
BuffLen:=Memo1.GetTextLen+1; GetMem(Buff, BuffLen); Memo1.GetTextBuf(Buff, BuffLen); | Текст из Memo1 копируется в динамическую переменную Buff. Для этого в BuffLen заносится длина текста, под переменную Buff отводится память и выполняется копирование. |
GetMem(FT, Length(FindText)+1); StrPCopy(FT, FindText); | Аналогично в динамическую переменную FT копируется содержимое строки поиска. |
P:=Buff+Memo1.SelStart+Memo1.SelLength; | В переменную P заносится адрес начала поиска. |
P:=StrPos(P, FT); | В переменную P заносится адрес подстроки, совпавшей с образцом для поиска. |
If P=Nil then MessageBeep(0) | Если адрес нулевой (образец не найден), то генерируется звуковой сигнал. |
Else begin Memo1.SelStart:=P-Buff; Memo1.SelLength:=Length(FindText) end; | Иначе, если образец найден, он выделяется в Memo1. |
FreeMem(FT); FreeMem(Buff, BuffLen); end; end; | В завершении процедуры разрушаются динамические переменные. |
Шаг 20. Для компонента ReplaceDialog1 в качестве обработчика события OnFind указать (в окне Object Inspector) обработчик этого же события компонента FindDialog1 (вот для чего в этой процедуре строка поиска FindText берется не у конкретного компонента FindDialog1 или ReplaceDialog1, а у источника события Sender).
Шаг 21. Для компонента ReplaceDialog1 ввести текст обработчика события OnReplace.
Текст обработчика | Комментарий |
With ReplaceDialog1 do Repeat | Организован цикл. |
if Memo1.SelText<>FindText then FindDialog1Find(Sender); | Если выделенный фрагмент не совпадает с образцом поиска, то вызовом обработчика события OnFind компонента FindDialog1 найти следующий совпадающий фрагмент. |
if Memo1.SelLength=0 then Break; | Если фрагмент не найден, то завершить цикл. |
Memo1.SelText:=ReplaceText; | Заменить выделенный фрагмент образцом для замены. |
until not (frReplaceAll in Options); | Если не выбран режим “Заменить все”, то остановить цикл. |
Самостоятельно: (реализация пунктов 3 и 6 для желающих получить 5 за лабораторную работу)
На панель добавить кнопку, позволяющуюВариант | Задание |
1, 6, 11, 16, 21, 26 | Отсортировать текст по числу слов в строке |
2, 7, 12, 17, 22, 27 | Переставить строки в обратном порядке |
3, 8, 13, 18, 23, 28 | Отсортировать текст по числу цифр в строке |
4, 9, 14, 19, 24, 29 | Отсортировать текст по числу лидирующих пробелов в строке |
5, 10, 15, 20, 25, 30 | Переставить строки по правилу 0-1, 2-3, 4-5,… |
2. На панель добавить кнопку, позволяющую сохранить в файле ‘proba. txt’
Вариант | Задание |
1, 7, 13, 19, 25 | Последние K строк |
2, 8, 14, 20, 26 | Строки с четным числом слов |
3, 9, 15, 21, 27 | K строк начиная с L-ой |
4, 10, 16, 22, 28 | Строки, в которых ровно K слов |
5, 11, 17, 23, 29 | Строки, в которых есть одинаковые слова |
6, 12, 18, 24, 30 | Строки, в которых все символы различные |
Числа K и L вводятся в компоненте SpinEdit, расположенном на панели (значения в SpinEdit должны соответствовать состоянию текста).
3. На панель добавить кнопку, позволяющую считать из файла (имя файла определяется в окне диалога) строки из задания 2 (вариант - следующий после Вашего). Строки или заменяют существующий текст, или добавляются к нему (в начало, в конец, после N-ой строки – на выбор пользователя). Все настройки определяются на диалоговой панели, заменяющей основную на время диалога. Предусмотреть возможность отмены диалога.
4. Добавить кнопку для выбора цвета фона текста.
5. С помощью компонента TMainMenu организовать главное меню проекта, разумно расположив в нем функции всех кнопок основной панели. (Естественно, лучше не переписывать эти функции, а назначать уже готовые обработчики для события OnClick пунктов меню).
6. Для желающих получить отметку 5 за лабораторную работу, необходимо реализовать в проекте пункты 2 и 3 дополнения (см. ниже).
Дополнение
1. Среди прочих компонент Memo обладает рядом свойств, доступных только во время работы приложения
Свойство | Значение |
SelText | Выделенный фрагмент текста |
SelLength | Длина выделенного фрагмента |
SelStart | Номер первого символа выделенного фрагмента начиная с начала всего текста. Если выделения нет, то позиция курсора внутри текста |
Modified | TRUE, если текст был изменен. |
2. Следующий программный код позволяет определить положение курсора в компоненте Memo1:
var X, Y : Integer;
begin
Y:=Memo1.Perform(EM_LINEFROMCHAR, Memo1.SelStart, 0);
X:=Memo1.Perform(EM_LINEINDEX, Y, 0);
Y:=Y+1;
X:=Memo1.SelStart-X+1;
end;
3. Для отмены действий в редакторе Memo1 можно воспользоваться следующим кодом:
Memo1.Perform(EM_UNDO, 0, 0);
Проверить возможность отмены действий можно, сравнив с нулем значение функции:
Memo1.Perform(EM_CANUNDO, 0, 0);


