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

Тема: Создание простого текстового редактора

Цель работы: получить практические навыки по работе с компонентами Edit, Memo, по масштабированию компонентов, по работе с диалогами.

 

Ход работы

 

Создать программу, которая при загрузке выдает окно ввода пароля:

 

 

Пароль разбивается на четыре части по 5 символов. В каждом поле предусмотреть автоматический переход в следующее поле при вводе 5 символов в текущем поле. В случае неверного ввода программа должна выдать сообщение об ошибке и предлагает ввести пароль снова (переходит в первое текстовое поле). В случае 5 неверных попыток кнопка "ОК" блокируется и продолжение работы с программой становится невозможным.

 

Указания: для первой формы задайте свойства: Caption="Регистрация. Осталось попыток : 5"; BorderStyle=bsDialog; Position=poDesktopCenter. На форме разместите 4 текстовых поля Edit, для которых задайте свойства: MaxLength=5 (длина в 5 символов), PasswordChar=* (символ для замены текста на экране), Text очистить.

 

Для автоматического перехода курсора между полями при вводе пароля в событии OnChange каждого поля введем код:

 

procedure TForm1.Edit1Change(Sender: TObject);

begin

//если в первое поле введено 5 символов

if Length(Edit1.Text)=5 then

//то переходим во второе поле

Edit2.SetFocus;

end;
  

procedure TForm1.Edit2Change(Sender: TObject);

begin

    //если во второе поле введено 5 символов

    if Length(Edit2.Text)=5 then

        //то переходим в третье поле

        Edit3.SetFocus;

end;
 

procedure TForm1.Edit3Change(Sender: TObject);

begin

    //если в третье поле введено 5 символов

    if Length(Edit3.Text)=5 then

        //то переходим в четвертое поле

        Edit4.SetFocus;

end;

 
  procedure TForm1.Edit4Change(Sender: TObject);

begin

    //если в четвертое поле введено 5 символов

    if Length(Edit4.Text)=5 then

        //то переходим на кнопку

        Button1.SetFocus;

end;

 

Добавим на форму кнопку со свойствами: Default=True; Caption=OK

Для подсчета количества попыток ввода пароля необходимо описать глобальную целую переменную в разделе Interface. Для этого после слова Var вставим строку вида:

 

k:integer=0;

 

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

 

procedure TForm1.Button1Click(Sender: TObject);

begin

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

    if Edit1.Text+Edit2.Text+Edit3.Text+eDit4.Text='11111111111111111111' then

    begin

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

        Free;

        //открываем окно редактора

        Form2.Show;

    end

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

    else

    begin

        //считаем количество попыток

        k:=k+1;

        //в заголовке окна меняем число оставшихся попыток

        Caption:='Регистрация. Осталось попыток : '+IntToStr(5-k);
           //выдаем сообщение об ошибке

        Application.MessageBox('Неверный пароль',

                               'Ошибка',

                               MB_OK+MB_IconStop);
           //ставим курсор в первое поле для повторного ввода

        Edit1.SetFocus;
 
       end;
 

    //если пользователь сделал 5 попыток

    if k=5 then

        //блокируем доступ к кнопке

        Button1.Enabled:=false;
 
   end;

 

При верном вводе пароля на экране появляется окно редактора, который состоит из многострочного текстового поля и кнопок.

 

 

 С помощью кнопки "Формат" должен открываться диалог форматирования символов. Сам диалог должен содержать кнопку Применить. С помощью кнопки "Цвет" должен открываться диалог для выбора цвета фона компонента Memo. Кнопки "Сохранить" и "Открыть" запрашивают ввод с клавиатуры  имени файла и сохраняют содержимое поля в файл или загружают содержимое файла в поле (в качестве пути к файлу используется папка с приложением). Предусмотреть проверку наличия файла на диске.

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

 

Указания: добавим в проект новую форму и зададим ей свойство Caption=Редактор, Width=700, Height=470. Чтобы форма не уменьшалась меньше начального размера установите свойства формы: Constraints - Minwidth = 700, Constraints - MinHeight = 470.

 

На форме разместите компонент Memo (Standard). Для масштабирования компонента на форме в свойстве Anchors установите все параметры в True. На форме разместите 4 кнопки. Для масштабирования кнопок в их свойстве Anchors установите параметр akButtom=true, другие параметры установите в false.

 

По умолчанию в поле Memo нет полосы прокрутки, но как только текст в поле не помещается, должна отображаться вертикальная полоса. Как только текст помещается – исчезает.

Для реализации данной функции вначале переведем компонент Memo в рисунок, затем получим высоту строки в точках. Затем множим высоту строки на количество строк - получим высоту всего текста в точках. Если высота текста превышает высоту компонента, то отображается полоса прокрутки. В противном случае полоса прокрутки исчезает. 

 

В событии OnChange поля введите код:

 

procedure TForm1.Memo1Change(Sender: TObject);

var

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

    cnv:TCanvas;

    //переменная для хранения высоты текста в точках

    row:integer;

begin

    //создаем экземпляр класса для изображения

    cnv := TCanvas.Create;

    try

        //привязываем ссылку экземпляра класса к ссылке поля Memo1

        cnv.Handle:=GetDC(Memo1.Handle);

        //устанавливаем на изображении шрифт, аналогичный полю Memo1

        cnv.Font.Assign(Memo1.Font);

        //в переменную записываем высоту строки текста в точках

        row:=cnv.TextHeight(Memo1.Text);

    except end;

    //если высота строки * количество строк + 1

    //больше высоты компонента   

    if (row*(Memo1.Lines.Count+1))>=Memo1.Height then

    begin

        //отображаем вертикальную полосу прокрутки

        Memo1.ScrollBars:=ssVertical ;

        //ставим курсор в текущую позицию

        Memo1.SelLength:=0;

    end

    //иначе - скрываем полосу прокрутки

    else

        Memo1.ScrollBars:=ssNone;

    //удаляем из памяти экземпляр класса   

    FreeAndNil(cnv);

end;

 

На форме разместите компонент FontDialog (Dialogs). В свойстве Options установите параметр fdApplyButton=true для отображения кнопки Применить.

Для форматирования текста для кнопки "Формат" напишем код:

 

procedure TForm2.Button1Click(Sender: TObject);

begin

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

    FontDialog1.Font.Assign(Memo1.Font);

    //если в окне форматирования пользователь нажал кнопку ОК

    if FontDialog1.Execute then

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

        Memo1.Font.Assign(FontDialog1.Font);

end;

  

Для работы кнопки "Применить" для компонента FontDialog в событии OnApply введите код:

 

procedure TForm2.FontDialog1Apply(Sender: TObject; Wnd: hWnd);

begin

    Memo1.Font.Assign(FontDialog1.Font);

end;

 

На форме разместите компонент ColorDialog (Dialogs).

Для изменения цвета фона поля Memo для кнопки "Цвет" напишем код:

 

procedure TForm2.Button2Click(Sender: TObject);

begin

    //если в окне выбора цвета пользователь нажал кнопку ОК

    if ColorDialog1.Execute then

        //применяем цвет к фону поля Memo

        Memo1.Color:=ColorDialog1.Color;

end;

 

Для сохранения содержимого поля в файл для кнопки Сохранить напишем код:

 

procedure TForm2.Button3Click(Sender: TObject);

begin

    //сохраняем содержимое поля Memo1 в файл file.txt на диске C:

    Memo1.Lines.SaveToFile('c:\file.txt');

end;

 

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

 

procedure TForm2.Button4Click(Sender: TObject);

begin

    //загружаем ранее сохраненный файл в поле Memo1

    Memo1.Lines.LoadFromFile('c:\file.txt');

end;

 

Обратите внимание, что при закрытии окна с текстом, программа продолжает работу (находится в ОЗУ).

Реализуйте корректное завершение программы.

 

Указания: данная проблема возникает потому, что главная форма (форма регистрации) была скрыта с экрана, но не закрыта.

Для завершения работы программы нужно закрыть главную форму проекта.

Для решения проблемы в событии OnClose второй формы добавьте команду:

 

//прервать работу приложения

Application.terminate;