Лабораторная работа №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);