Практическое занятие № 16

Тема: "Создание многодокументного редактора"

Цель занятия: получить практические навыки со созданию программ с MDI интерфейсом и использованию компонента RichEdit

 

Ход работы

 

1. Создать главную MDI форму вида:

 

 

Окно имеет меню с перечнем команд: Файл - (Создать, Открыть..., Выход), Окно - (Каскадом, Слева направо,  Сверху вниз).

 

Указания: для формы задайте свойства: Caption=Текстовый редактор, FormStyle=fsMDIForm, WindowState=wsMaximized (окно будет развернуть на весь экран).

На форму нанесите компонент MainMenu (Standard). Щелкните два раза на компоненте и введите названия нужных пунктов меню.

В меню Окно должен отображаться список открытых дочерних окон. Для этого в свойстве WindowMenu формы укажите имя раздела меню Окно.

 

2. Создать дочернюю форму вида:

 

 

Форма содержит многострочный компонент RichEdit. В заголовке формы отображается номер документа. При открытии дочерней формы в главном меню происходит добавление новых разделов и команд: Файл - (Создать, Открыть..., Сохранить, Сохранить как..., Закрыть, Выход), Правка - (Отменить, Вырезать, Копировать, Вставить, Выделить все), Формат - (Шрифт, Выравнивание (Влево, По центру, Вправо), Список).

 

Указания: с помощью кнопки NewForm создайте новую форму. Для формы задайте свойство FormStyle=fsMDIChild. Форма будет создаваться динамически. Выполните команду Project - Options. На закладке Forms перенесите форму Form2 в список Available forms.

Так как форма будет создаваться динамически, то для ее удаления из памяти после закрытия в событии OnClose формы введите код:

 

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);

begin

    action:=cafree;

end;

 

Нанесите на форму компонент RichEdit (Win32). Для компонента задайте свойства: Align=alClient (растягиваем поле на всю форму), Lines очистить.

 Для создания меню нанесите на форму компонент MainMenu (Standard). Двойным щелчком откройте редактор меню и создайте нужные пункты меню как указано  в задании. Для команды Выравнивание нужно создать подменю. Для этого щелкните на команду Выравнивание правой кнопкой и выберите команду Create Submenu.

При открытии дочерней формы необходимо, чтобы соответствующие пункты встраивались в меню главной формы. Для этого каждому разделу меню на дочерней формы в свойстве GroupIndex присвойте порядковые номера: Файл=1, Правка=2, Формат=3.

Нумерацию нужно проставить и для разделов главного меню. С помощью кнопки ViewForm перейдите на главную форму Form1, двойным щелчком на компоненте MainMenu отройте редактор меню и присвойте номера для разделов: Файл=1, Окно=4.

Для корректного открытия и сохранения содержимого файлов опишем внутри класса дочерней формы текстовое поле для запоминания имени файл. Перейдите в код дочерней формы, найдите описание класса формы ( TForm2 = class(TForm)) и в разделе public опишите поле класса:

 

fname:string;

 

3. Для пунктов меню главной формы напишите код, выполняющий соответствующие действия.

 

Указания:  в разделе Interface модуля формы опишем глобальную переменную для нумерации открытых дочерних форм.

 

kol_child:integer=0;

 

Для команды Создать напишем код вида:

 

procedure TForm1.N5Click(Sender: TObject);

begin

    //создаем дочернюю форму

    form2:=tform2.create(nil);

    form2.show;

    form2.repaint;

    //наращиваем счетчик дочерних форм на 1

    kol_child:=kol_child+1;

    //в заголовке дочерней формы отображаем ее номер

    form2.caption:='Документ: '+inttostr(kol_child);

end;

 

Для открытия файлов добавим на форму компонент OpenDialog (Dialogs) и зададим свойства: DefaultExt=rtf, Filter=Форматированный текст|*.rtf |Обычный текст|*.txt.

 

Если в диалоге открытия файла пользователь указал тип "Форматированный текст", то текст должен загружаться с форматированием. Если же указан тип "Обычный текст", то текст должен загружаться без форматирования. Для этого в событии OnTypeChange компонента OpenDialog напишем код:

 

procedure TForm1.OpenDialog1TypeChange(Sender: TObject);

begin

    //если в диалоге выбран первый фильтр (форматированный текст)

    if opendialog1.filterindex=1 then

        //открываем текст с форматированием

        form2.richedit1.plaintext := false

    //иначе, если в диалоге выбран другой фильтр (обычный текст)

    else

        //иначе сохраняем текст без форматирования

        form2.richedit1.plaintext := true;

end;

 

Для команды Открыть напишем код:

 

procedure TForm1.N6Click(Sender: TObject);

begin

       //если в диалоге открытия файла была нажата кнопка Открыть

    if opendialog1.execute=true then

    begin

        //создаем новое дочернее окно

        form2:=tform2.create(nil);

        form2.show;

        form2.repaint;

        //в дочернее окно в компонент richedit загружаем выбранный файл

        form2.RichEdit1.Lines.LoadFromFile(opendialog1.filename);

        //в специальную переменную запоминаем имя загруженного файла

        form2.fname:=opendialog1.filename;

             //в заголовке окна отображаем имя открытого файла

        form2.caption:=extractfilename(opendialog1.filename);

        //компоненту richedit ставим отметку, что файл не редактировался

        form2.RichEdit1.Modified:=false;

    end;

end;

 

Для команды Выход напишем код:

 

procedure TForm1.N7Click(Sender: TObject);

begin

    //закрываем главную форму (завершаем работу программы)

    form1.close;

end;

 

Для команды Каскадом напишем код:

 

procedure TForm1.N4Click(Sender: TObject);

begin

    //упорядочиваем дочерние формы каскадом

    cascade;

end;

 

Для команды Слева направо напишем код:

 

procedure TForm1.N9Click(Sender: TObject);

begin

    //упорядочиваем дочерние формы слева направо

    tilemode:=tbVertical;

    Tile;

end;

 

Для команды Сверху вниз напишем код:

 

procedure TForm1.N10Click(Sender: TObject);

begin

    //упорядочиваем дочерние формы сверху вниз

    tilemode:=tbHorizontal;

    Tile;

end;

 

Запретим выход из программы пока будут открыты дочерние окна. Для этого в событии OnCloseQuery формы напишем код:

 

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

begin

    //если есть открытые дочерние окна

    if mdichildcount>0 then

    begin

        //выдаем сообщение

        application.MessageBox('Закройте все дочерние окна перед выходом из программы','Выход невозможен',mb_ok+mb_iconstop);

        //запрещаем закрытие окна программы

        canclose:=false;

    end;

end;

 

4. Для команд меню дочерней формы написать код, выполняющий соответствующие действия.

 

Указания: Команда Создать должна выполнять те же действия, что и аналогичная команда в меню главной формы. Поэтому код для команды может иметь вид:

 

procedure TForm2.N5Click(Sender: TObject);

begin

    //запускаем тот же код, что и для команды Создать главной формы Form1

    //при условии, что команда Создать имеет имя N5

    Form1.N5Click(sender);

end;

 

Команда Открыть должна выполнять те же действия, что и аналогичная команда в меню главной формы. Поэтому код для команды может иметь вид:

 

procedure TForm2.N6Click(Sender: TObject);

begin

    //вызываем процедуру для команды открыть главной формы Form1

    //при условии, что команда Открыть имеет имя N6

    Form1.N6Click(Sender);

end;

 

Для сохранения файла добавьте на форму компонент SaveDialog (Dialogs) и задайте свойства DefaultExt=rtf, Filter=Форматированный текст|*.rtf |Обычный текст|*.txt.

 

Если в диалоге открытия файла пользователь указал тип "Форматированный текст", то текст должен сохраняться с форматированием и с расширением "rtf". Если же указан тип "Обычный текст", то текст должен загружаться без форматирования и с сохранением "txt". Для этого в событии OnTypeChange компонента SaveDialog напишем код:

 

procedure TForm2.SaveDialog1TypeChange(Sender: TObject);

begin

    //если в диалоге выбран первый фильтр (форматированный текст)

    if savedialog1.filterindex=1 then

    begin

        //сохраняем текст с форматированием

        richedit1.plaintext := false;

        //то к имени файла будет подставляться расширение rtf

        savedialog1.defaultext:='rtf';

    end

    //если в диалоге выбран другой фильтр (обычный текст)

    else if savedialog1.filterindex=2 then

    begin

        //иначе сохраняем текст без форматирования

        richedit1.plaintext := true;

        //будет подставляться расширение txt

        savedialog1.defaultext:='txt';

    end;

end;

 

Для команды Сохранить как... напишем код:

 

procedure TForm2.N8Click(Sender: TObject);

begin

    //будем обращаться к активному дочернему окну

    with (form1.ActiveMDIChild as tform2) do
        begin

        //если в окне сохранения файла нажата кнопка Сохранить

        if savedialog1.execute=true then

        begin

            //содержимое окна записывается в файл

            richedit1.Lines.SaveToFile(savedialog1.filename);

            //в переменную запоминается имя файла

            fname:=savedialog1.filename;

            //в заголовке окна отображается имя файла

            caption:=extractfilename(savedialog1.filename);

            //делается отметка, что файл не редактировался (уже сохранен)

            richedit1.Modified:=false;

        end;

    end;

end;

 

Для команды Сохранить напишем код:

 

procedure TForm2.N7Click(Sender: TObject);

begin

    //если переменная с именем файла не пустая,

    //то это значит, что файл либо был открыт с диска,

    //либо его уже сохраняли

    if fname<>'' then

    begin

        //сохраняем изменения в этот файл

        richedit1.Lines.SaveToFile(fname);

        //делаем отметку, что файл не изменялся (уже сохранен)

        richedit1.modified:=false;

    end

    //если же переменная с именем файла пустая,

    //то это значит, что файл новый

    else

        //вызываем процедуру для команды меню Сохранить как...

        //при условии, что команда Сохранить как... имеет имя N8

        Form2.N8Click(Sender);

end;

 

Для команды Закрыть напишем код:

 

procedure TForm2.N10Click(Sender: TObject);

begin

    //закрываем текущее окно

    close;

end;

 

Команда выход делает те же действия, что и аналогичная команда в меню главной формы. Код для команды может иметь вид:

 

procedure TForm2.N11Click(Sender: TObject);

begin

    //запускаем тот же код, что и для команды Выход главной формы Form1

    //при условии, что команда Выход на главной форме имеет имя N7

    Form1.N7Click(Sender);

end;

 

Для команды Отменить напишем код:

 

procedure TForm2.N13Click(Sender: TObject);

begin

    //отменяем последнее действие

    richedit1.Undo;

end;

 

Для команды Вырезать напишем код:

 

procedure TForm2.N15Click(Sender: TObject);

begin

    //вырезаем выделенный фрагмент в буфер обмена

    richedit1.CutToClipboard;

end;

 

Для команды Копировать напишем код:

 

procedure TForm2.N16Click(Sender: TObject);

begin

    //копируем выделенный фрагмент в буфер обмена

    richedit1.CopyToClipboard;

end;

 

Для команды Вставить напишем код:

 

procedure TForm2.N17Click(Sender: TObject);

begin

    //вставляем содержимое буфера обмена в позицию курсора

    richedit1.PasteFromClipboard;

end;

 

Для команды Выделить все напишем код:

 

procedure TForm2.N19Click(Sender: TObject);

begin

    //выделяем весь текст

    RichEdit1.SelectAll;

end;

 

Для форматирования текста добавьте на форму компонент FontDialog (Dialogs). Для команды Шрифт напишем код:

 

procedure TForm2.N20Click(Sender: TObject);

begin

    //вызываем диалог форматирования шрифта

    if fontdialog1.execute=true then

        richedit1.selattributes.Assign(fontdialog1.Font);

end;

 

Для команды Выравнивание - Влево напишем код:

 

procedure TForm2.N22Click(Sender: TObject);

begin

    //выравнивает текст влево

    richedit1.paragraph.alignment:=taLeftJustify;

end;

 

Для команды Выравнивание - По центру напишем код:

 

procedure TForm2.N23Click(Sender: TObject);

begin

    //выравнивает текст по центру

    richedit1.paragraph.alignment:=taCenter;

end;

 

Для команды Выравнивание - Вправо напишем код:

 

procedure TForm2.N24Click(Sender: TObject);

begin

    //выравнивает текст вправо

    richedit1.paragraph.alignment:=taRightJustify;

end;

 

Для команды Список напишем код:

 

procedure TForm2.N25Click(Sender: TObject);

begin

    //если списка нет

    if richedit1.paragraph.Numbering=nsNone then

    begin

        //делаем текст списком

        richedit1.paragraph.Numbering:=nsBullet;

        //ставим флажок для нужного пункта меню

        //при условии, что команда Список имеет имя N25

        n25.checked:=true;

    end

    //если список есть

    else

    begin

        //убираем список из текста

        richedit1.paragraph.Numbering:=nsNone;

        //снимаем флажок для нужного пункта меню

        //при условии, что команда Список имеет имя N25

        n25.checked:=false;

end;

end;

 

При закрытии формы нужно проверять, сохранено ли содержимое окна. Если нет, то выдавать запрос на сохранение или отмену сохранения текста.

Для этого в событии OnCloseQuery формы напишем код:

 

procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

begin

    //если содержимое поля отмечено как изменившееся,

    //то это значит, что изменения не сохраняли

    if richedit1.Modified =true then

    //выдаем запрос на сохранение и обрабатываем ответ

        case application.MessageBox(pchar('Сохранить изменения в файле '+fname+'?'), 'Сохранение данных', mb_YesNoCancel+mb_iconquestion) of

            //если пользователь ответил Да,

            //то вызываем код для команды меню Сохранить

             //при условии, что команда Сохранить имеет имя N7

            idyes: N7Click(Sender)

                //если пользователь ответил Отмена,

            //отменяем закрытие окна дочерней формы

            idcancel: canclose:=false;

        end;

end;

 

5. Создадим форму для регистрации в программе:

 

 

Указания: с помощью кнопки NewForm   добавьте новую форму. Для формы задайте свойства: BorderStyle=bsDialog, Caption=Регистрация.

На форму нанесите компонент Label (Standard) и задайте свойство Caption=Пароль.

На форму нанесите компонент Edit (Standard) и задайте свойства: PasswordChar=*, Text очистить.

На форму нанесите компонент Button (Standard) и задайте свойство Caption=Войти.

 

Форма регистрации должна запускаться первой, однако MDI форма всегда должна быть главной в проекте. Следовательно окно регистрации должно запускаться до старта основного приложения через файл проекта.

Выполните команду Project-Options и перенесите форму регистрации в список Available Forms.

 

В коде формы регистрации опишите глобальную вспомогательную переменную. Она будет играть роль признака ввода верного пароля: если пароль верный, то переменная = 1, иначе - 0.

 

//по умолчанию предполагаем, что пароль не верный

key: integer=0;

 

Для кнопки напишем код:

 

procedure TForm3.Button1Click(Sender: TObject);

begin

    //если пароль равен заданному

    if edit1.text='111' then

    begin

        //активируем переменную-признак

        key:=1;

        //закрываем окно регистрации

        Close;

    end

    //если пароль не верный

    else

    begin

        //выдаем сообщение

        Application.MessageBox('Пароль неверный. Доступ запрещен.','Ошибка регистрации',MB_OK+MB_ICON_EROR);

        //ставим курсор в поле для повторного ввода

        Edit1.SetFocus;

    end;

end;

 

Добавим для формы регистрации анимационный эффект появления от центра и исчезновения в центр.

 

Указания: в событии OnShow формы введите код:

 

procedure TForm3.FormShow(Sender: TObject);

begin

    //окно появляется из точки в центре на протяжении 1 секунды   

    AnimateWindow(Handle,1000, AW_Center);

end;

 

При закрытии формы нужно не только указать анимационный эффект, но и проверить значение переменной key. В событии OnClose формы введите код:

 

procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);

begin

    //окно исчезает в центр в точку на протяжении 1 секунды

    AnimateWindow(Handle,1000, AW_Hide or AW_Center);

   

    //если переменная key=0 (пароль не верный)

    if key=0 then

        //завершаем работу приложения

        Application.Terminate;

end;

 

Появление формы регистрации должно происходить до запуска главной программы.

 

Указания: с помощью команды Project - View Source откройте файл проекта. После ключевого слова BEGIN введите код:

 

//создаем в памяти форму регистрации

form3:=TForm3.Create(nil);

//отображаем ее в модальном виде,

//т.е. далее команды не выполняются пока окно не будет закрыто

form3.ShowModal;