Задание 3

Задача: формировать список автовладельцев (фамилия; номер, марка, цвет автомобиля и код региона), редактировать данные, осуществлять поиск, вводить и выводить списки в файлы. Такую программу Вам предстоит сейчас написать.

Вид главного окна показан на рис.1. Оно содержит следующие компоненты: Edit – для ввода фамилии; два компонента MaskEdit – для ввода по шаблону номера и кода, два комбинированных списка ComboBox для выбора марки цвета и Memo - многострочный редактор.

Рис. 1 Вид приложения

1. Установите заголовок формы Владельцы автомобилей, рамку окна сделайте тонкой (свойство BorderStyle значение bsSingle), чтобы окно не могло изменять свои размеры.

2. Создайте главное меню; пусть оно содержит пункты: Файл (с подпунктами Открыть, Сохранить, Выход), Опции (с единственным пунктом Настройки…).

3. Вставьте пять компонент Label, задав соответствующий текст в свойстве Caption.

4. Используйте Edit для ввода фамилии. Для Edit определите максимальную длину строки MaxLenght=15, шрифт Times New Roman|Полужирный|12, а для автоматической подстройки размеров объекта установите AutoSize=true.

5. Вставьте компонент MaskEdit с MaxLenght=6 для ввода номера автомобиля по шаблону и MaskEdit с MaxLenght=2 для задания кода региона.

6. Задайте шаблон для ввода номера: в поле MaskEdit введите строку L999LL;1;X[25]; а для кода региона - 99;1;X.

7. Для выбора марки и цвета автомобиля добавьте два компонента ComboBox. Для ComboBox1 щелчком на свойстве Items откройте диалоговое окно и введите список марок автомобилей. Аналогичное окно для ComboBox2 заполните строками с названиями цвета.

8. Добавьте в форму редактор с именем Memo1 (компонент Memo) для формирования списка. Обеспечьте вертикальную и горизонтальную прокрутку.

9. Вставьте кнопку для добавления информации в список.

10. Отделите меню от остальных объектов, вставив компонент Bevel. Привяжите его к верхнему краю рабочей области окна (Align = alTop), если необходимо, измените размеры. и поэкспериментируйте со свойствами Shape и Style.

Для полноценной обработки информации Ваша программа должна уметь извлекать введенный в поля текст; работать с выделенными фрагментами текста и с буфером обмена. Эти действия выполняются над фрагментами текста обработчиками событий с помощью анализа свойств и применением методов, доступных соответствующим компонентам.

Введенный текст содержится в свойстве Text полей ввода. MaskEdit, кроме того, в свойстве EditText содержит промежуточный, черновой вариант текста.

Метод Clear() очищает текстовые объекты, заменяя строки свойства Text на пустые строки. Свойство Modified разрешает проверить, изменялся ли текст во время редактирования.

Метод GetTextBuf() позволяет извлечь текст из объекта и возвращает количество введенных символов, например:

char buf[256];

int count=Edit1->GetTextBuf(buf, sizeof(buf));

Компонент Memo использует для хранения текста свойство Lines. Это массив строк класса Strings, который определен в VCL специально для поддержки строковых операций. Число строк в массиве содержит свойство Memo1->Lines->Count. Программно к отдельной строке можно обратиться по номеру, например,

String s = Memo1->Lines->Strings[0];

Для ввода текста имеется специальный редактор (для его вызова дважды щелкните на свойстве Lines или на кнопке с многоточием).

Работа с выделенными фрагментами и с буфером обмена одинакова для всех трех рассматриваемых компонентов.

При выделении фрагмента текст автоматически помещается в строку SelText, а его начало и длина – в целочисленные свойства SelStart и SelLength, где их можно будет найти программно. Для работы с фрагментом имеется несколько методов: SelectAll() выделит весь текст компонента, ClearSelection() очистит весь выделенный фрагмент, GetSelTextBuf() копирует выделенный текст в символьную строку и возвратит число символов, а SetSelTextBuf заменит выделенный текст нуль терминированной строкой. Вот прототипы двух последних методов:

int GetSelTextBuf(char * Buffer, int BufSize));

void SetSelTextBuf(char * Buffer);

Для работы с буфером обмена также существует несколько методов, например, CopyToClipboard() копирует в него выделенный текст, а PasteFromClipboard() вставляет содержимое буфера в объект.

Создадим обработчики событий.

11. Для вызова разработанного ранее диалогового окна (Form2), пункт меню Настройка… должен иметь следующий обработчик:

void __fastcall TForm1::Optionclick(TObject *Sender)

{ // Сохранить текущие пометки радиокнопок и переключателей

bool Radio1= Form2->RadioButton1->Checked;

bool Radio2= Form2->RadioButton2->Checked;

bool Radio3= Form2->RadioButton3->Checked;

bool Check1=Form2->CheckBox1->Checked;

bool Check2=Form2->CheckBox2->Checked;

int result=Form2->ShowModal();

if (result==mrOk)

{ // Прочесть установки и выполнить действия

if (Form2->RadioButton1->Checked)

{ ComboBox1->Enabled= true;

MaskEdit1->Enabled= false;

}

if (Form2->RadioButton2->Checked)

{ ComboBox1->Enabled= false;

MaskEdit1->Enabled= true;

}

if (Form2->RadioButton3->Checked)

{ ComboBox1->Enabled= true;

MaskEdit1->Enabled= true;

}

if (Form2->CheckBox1->Checked)

Button1->Enabled= true;

else

Button1->Enabled= false;

if (Form2->CheckBox2->Checked)

Memo1->ReadOnly=false;

else

Memo1->ReadOnly=true;

}

if (result==mrCancel)

// восстановить значения переключателей

{ Form2->RadioButton1->Checked=Radio1;

Form2->RadioButton2->Checked=Radio2;

Form2->RadioButton3->Checked=Radio3;

Form2->CheckBox1->Checked=Check1;

Form2->CheckBox2->Checked=Check2;

}

12. В начале каждой строки списка будем вставлять номер. Для определения номера строки воспользуемся свойством, которое хранит количество строк в компоненте Memo: Memo -> Lines -> Count.

13. Кнопка, отвечающая за внесение абонента в список, после того как поля ввода были заполнены, должна иметь обработчик события OnСlick. Вот такой код этот обработчик может содержать:

void __fastcall TForm1::Button1Click(TObject *Sender)

void __fastcall TForm1::Button1Click(TObject *Sender)

{ char nom[6], string[10]="�";

int nomer;

AnsiString record_auto;

// получение номера текущей записи

nomer= Memo1->Lines->Count;

itoa (nomer,nom,10);

for (int i=0; i<5; i++)

string[i]=' ';

string[5];

strcat(string,nom);

strcat (string,". ");

// формирование записи

record_auto=(AnsiString) string;

record_auto+=Edit1->Text;

record_auto+=" ";

record_auto+=ComboBox1->Text;

record_auto+=" ";

if (MaskEdit1->Enabled&&MaskEdit2->Enabled)

{ record_auto+=MaskEdit1->Text;

record_auto+=" ";

record_auto+=MaskEdit2->Text;

record_auto+=" ";

}

if (ComboBox2->Enabled)

{record_auto+=ComboBox2->Text;

record_auto+=" ";

}

Memo1->Lines->Insert(nomer,record_auto);

}

Открытие и сохранение файла со списком абонентов будем осуществлять, как это и принято в Windows, в стандартных диалоговых окнах меню Файл. Для этого используем компоненты OpenDialog и SaveDialog. Вместе с методом Execute они обеспечат возврат имени файла, выбранного пользователем (свойство FileName); код ввода и сохранения данных напишите самостоятельно.

14. Ввставьте компонент SaveDialog в Form1, оставьте его имя по умолчанию, измените заголовок на Сохранение списка (свойство Title);

15. двойным щелчком на значении свойства Filter в инспекторе объектов, откройте окно редактора фильтров, в левой части которого задается текстовое описание типов открываемых файлов, а в правой – маска отбора файлов. Введите для нашего примера: слева – Текстовые файлы (*.txt), а справа – *.txt.

16. создайте обработчик события для пункта меню Файл | Сохранить. Вот его возможный код:

void __fastcall TForm1::SaveDialogClick(TObject *Sender)

{ if (SaveDialog1->Execute())

{ Memo1->Lines->SaveToFile(SaveDialog1->FileName);

Memo1->Modified=false;

}

}

17. Для открытия файла следует выбрать компонент Open File, установить соответствующий заголовок, фильтр идентичный предыдущему, а в обработчик пункта меню Файл | Открыть внести следующий код:

void __fastcall TForm1::OpenDialogClick(TObject *Sender)

{ if (Memo1->Modified)

{ int rezult=Application-> MessageBox

("Список был изменен. Сохранить изменения?",

"Сообщение",MB_YESNOCANCEL | MB_ICONWARNING);

if (rezult==IDYES) SaveDialogClick(0);

if (rezult==IDCANCEL) return;

}

OpenDialog1->FileName="";

if (OpenDialog1->Execute())

{ if (Memo1->Lines->Count>0) Memo1->Clear();

Memo1->Lines->LoadFromFi>