
Русифицированное диалоговое окно
Метод MessageBoxобъектаApplicationиспользует одноименную функциюWinAPIи позволяет выводить длинные текстовые сообщения (более 255 символов), заголовки на русском языке и русские надписи на кнопках (конечно, в русифицированных версияхWindows). Этим данный метод выгодно отличается от всех других способов создания информационных окон.
В документации метод объявлен так
int __fastcall MessageBox(const char *Text, const char *Caption,
int Flags);
Text– текст информационного сообщения;
Caption– заголовок окна;
Flags– параметр определяет набор иконок и кнопок.
Для задания необходимого набора кнопок используются следующие константы:
MB_ABORTRETRYIGNORE– “Стоп - Повтор – Пропустить”;
MB_OK– кнопкаOK;
MB_OKCANCEL– “OK– Отмена”;
MB_RETRYCANCEL– “Повтор – Отмена”;
MB_YESNO– “Да – Нет”;
MB_YESNOCANCEL– “Да - Нет – Отмена”.
Для указания характера выводимой информации можно использовать соответствующие пиктограммы:
MB_ICONEXCLAMATION– замечание, предупреждение;
MB_ICONINFORMATION– вывод информационного сообщения;
MB_ICONQUESTION– вопрос пользователю;
MB_ICONSTOP– запрет, ошибка.
При работе пользователь щелкнет одну из кнопок, для ее идентификации используются значения возвращаемые методом MessageBox(IDABORT– “Стоп”; IDCANCEL - “Отмена”;IDIGNORE– “Пропустить”;IDNO– “Нет”;IDOK– “OK”;IDRETRY– “Повтор”;IDYES– “Да”).
В следующем примере пользователю предлагается вопрос и два варианта ответов (кнопки Yes – No):
if(Application->MessageBox("Выберете одну из возможностей”, "Вопрос пользователю",MB_YESNO+MB_ICONQUESTION) ==IDNO)
Label1->Caption="Ответ <Нет>";
else
Label1->Caption="Ответ <Да>";
Репозиторий объектов
Репозиторий содержит готовые объекты (проекты, формы, диалоговые окна и др.), которые можно использовать для создания нового приложения или добавления в существующий проект. Команда меню File | New… открывает окно репозиторияNew Items. Для удобства поиска объекты располагаются на нескольких вкладках, предопределенных средой (New, Forms, Dialogs, Projectsи т.д.) или созданных пользователем.
Удобнее всего добавлять в открытый проект объект из репозитория путем копирования (в окне репозитория при нажатой радио-кнопке Copyщелкнуть кнопкуOk). Например, можно в своей программе использовать окноAbout(вкладкаForms). После этого с формойAboutможно работать так, как будто она только что была создана (изменять ее свойства, добавлять новые компоненты). Конечно, файл и модуль этой формы следует сохранить в каталоге своего проекта.
В репозитории можно также хранить и разработанные объекты. Например, для сохранения формы следует: сохранить модуль формы командой File | Save; в контекстном меню формы выбрать пунктAdd to Repository;в появившемся окне указать вкладку репозитория и выбрать иконку, сопроводительную надпись и т.д.
Обработчики событий
Воспользуемся нашим примером и рассмотрим некоторые события, для которых необходим специальный код обработки.
Событие OnCreate возникает в момент создания формы. Им можно воспользоваться, чтобы сделать некоторые начальные установки. Например, присвоить значения переменным, изменить свойства компонент расположенных на форме или самой формы.
В данном случае обработчик события используется для заполнения ячеек таблицы начальными значениями.
void __fastcall TForm1::FormCreate(TObject *Sender)
{
int i, j;
// В нулевом столбце – номера строк
for (i=1;i<=m; i++)
StringGrid1->Cells[0][i]="Строка" + IntToStr(i);
// В нулевой строке – номера столбцов
for (j=1; j<=n; j++)
StringGrid1->Cells[j][0]="Столбец" + IntToStr(j);
// Значения ячеек обнуляются
for (i=1;i<=n; i++)
for (j=1; j<=m; j++)
StringGrid1->Cells[j][i]="0";
}
Оформить каждую ячейку таблицы компонента StringGridможно, воспользовавшись событиемOnDrawCell, которое возникает каждый раз при необходимости перерисовки ячейки. ПараметрыARow, AColзадают номер ячейки, аRect– координаты прямоугольника для рисования. Следующий код задает новый цвет фона для фиксированных ячеек компонентаStringGrid1:
void __fastcall TForm1::StringGrid1DrawCell(Tobject
*Sender, int ACol,int ARow, TRect &Rect,
TGridDrawState State)
{ if(ARow==0 &&ACol==0) //Ячейка(0,0)– красный фон
{ StringGrid1->Canvas->Brush->Color = clRed;
StringGrid1->Canvas->FillRect(Rect);
}
else
{ if ( ACol==0) // нулевой столбец: фон - желтый
{ StringGrid1->Canvas->Brush->Color =
clYellow;
StringGrid1->Canvas->FillRect(Rect);
StringGrid1->Canvas ->
TextOut(Rect.Left+2,Rect.top+2,
StringGrid1->Cells[ACol][ARow]);
}
// нулевая строка: фон – бледно-голубой
if ( ARow==0)
{ StringGrid1->Canvas->Brush->Color =
clSkyBlue;
StringGrid1->Canvas->FillRect(Rect);
StringGrid1->Canvas->
TextOut(Rect.Left+2,Rect.top+2,
StringGrid1->Cells[ACol][ARow]);
}
}
}
Обработчик команды меню Вычисления – Настройки… вызывает диалоговое окно (Form5) в модальном режиме и после его закрытия проверяет настройки произведенные пользователем. Кнопки вычислений (Button1,Button2иButton3) на главной форме становятся доступны в зависимости от выбранной части массива для проведения вычислений (возможные варианты представлены вComboBox1наForm5):
void __fastcall TForm1::OptionClick(TObject *Sender)
{
Form5->ShowModal();
int id = Form5 -> ComboBox1 -> ItemIndex;
Button1->Enabled=false;
Button2->Enabled=false;
Button3->Enabled=false;
switch (id)
{
case 0: Button1 -> Enabled = true;
break;
case 1: Button2 -> Enabled = true;
break;
case 2: Button3 -> Enabled = true;
break;
}
}
Команда меню Вычисления - Вычислитьвыполняет те же действия, что и отдельные кнопки, но предварительно выясняет, как именно производятся вычисления: по строкам, по столбцам или для всего массива. Чтобы программный код не повторялся, в обработчике команды производятся обращения к обработчикам кнопок, так как будто щелчок на кнопке произведен пользователем:
void __fastcall TForm1:CalculateClick(TObject *Sender)
{
int id = Form5 -> ComboBox1 -> ItemIndex;
switch (id)
{
case 0: Button1Click(this);
break;
case 1: Button2Click(this) ;
break;
case 2: Button3Click(this) ;
break;
}
}
Рассмотрим обработчики команд выполняющих непосредственно вычисления в двумерном массиве. Кнопка Button1отвечает за обработку всего массива:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int i, j;
char str[40];
bool flag = false;
float a[6][6];
float b;
// В цикле производится попытка перевести строковые
// данные ячеек таблицы
// в вещественные числа и записать их в массив a.
// При возникновении ошибок
// элемент массива a[i][j] обнуляется
for (i=0; i<n; i++)
for (j=0; j<m; j++)
{ try
{a[i][j]=(StrToFloat)(StringGrid1->
Cells[j+1][i+1]);
}
catch (EConvertError&)
{ a[i][j]=0;
flag = true;}
}
int id=Form5->RadioGroup1->ItemIndex;
switch (id)
{
case0: // Вычислить среднее арифметическое
//.Обращение к функции модуля “Unit2”
strcpy(str," SA = ");
break;
case 1:
//Здесь следует разместить обращения к
//функциям модуля “Unit2”
break;
//...
case3: // Вычисление максимального значения
// max_massiv (a,b); - вызов функции
strcpy(str," MAX = ");
break;
//…
}
// Создание формы для вывода результатов
Application->CreateForm(__classid(TForm6),&Form6);
Form6 -> Caption =
Form5->RadioGroup1->Items->Strings[id];
// Вывод результата
AnsiString AStr;
AStr = (AnsiString)str + FloatToStr(b);
Form6 -> Memo1 -> Lines->Insert(0,AStr);
// После проверки наличия ошибок в компонент Memo1
// добавляется информационное сообщение
if(flag)
Form6 -> Memo1 -> Lines->Insert(1,"В исходных
данных найдены ошибки");
if (!Form6->Visible)
Form6->ShowModal();
delete(Form6);
}
Щелчок на кнопке Button2приводит к вычислениям по строкам. Результаты вычисления помещаются в столбец компонентаForm3->StringGrid1.
void __fastcall TForm1::Button2Click(TObject *Sender)
{ int i, j;
bool flag=false;
float a[6][6];
float b[6] = {0};
for (i=0; i<n; i++)
for (j=0; j<m; j++)
{ try
{a[i][j]=(StrToFloat)(StringGrid1->
Cells[j+1][i+1]);
}
catch (EConvertError&)
{ a[i][j]=0;
flag=true;
}
}
// При наличии ошибок в исходных данных
// выдается соответствующее информационное сообщение.
// Вычисления не производятся.
if(flag)
Application->MessageBox("Массив содержит некорректные данные", "Информация",MB_OK+MB_ICONEXCLAMATION);
else
{
int id=Form5->RadioGroup1->ItemIndex;
switch (id)
{
case0: // Вычисление среднего арифметического
sr_ar_stroka (a,b);
break;
case 1:
//Здесь следует разместить обращения
//к функциям модуля “Unit2”
//...
break;
//...
}
// Вывод результатов на Form3
for (i=0; i<n; i++)
Form3->StringGrid1->Cells[1][i+1] =
(FloatToStr)(b[i]);
Form3 -> Caption=Form5->
RadioGroup1->Items->Strings[id];
Form3->Show();
}
}
Следующие два обработчика используют стандартные диалоговые окна сохранения и открытия файлов. Компонент StringGridне имеет метода для сохранения значений в файл, но можно воспользоваться методом компонентаMemo. Для этого на главную форму поместимMemo1и сделаем его невидимым во время выполнения программы (свойствоVisible = false).
void __fastcall TForm1::SaveClick(TObject *Sender)
{
AnsiString FName;
int i, j;
if (SaveDialog1 -> Execute())
{
FName=SaveDialog1->FileName;
Memo1->Clear();
// Значения из ячеек добавляем по порядку в строки
// компонента Memo1
for (i=1; i<=n; i++)
for (j=1; j<=m; j++)
Memo1->Lines ->Add(StringGrid1->
Cells[i][j]);
// Сохранить строки в файле с именем FName
Memo1->Lines->SaveToFile(FName);
}
}
Команда Файл – Открытьосуществляет обратные действия, то есть вводит строковые данные вMemo1, а затем по порядку записывает строчки в ячейки компонентаStringGrid1->Cells[i][j].
void __fastcall TForm1::OpenClick(TObject *Sender)
{
AnsiString FName, s;
int i, j, id;
if (OpenDialog1 -> Execute())
{
FName=OpenDialog1->FileName;
// Загрузить данные из файла
Memo1->Lines->LoadFromFile(FName);
id=0;
for (i=1; i<=n; i++)
for (j=1; j<=m; j++)
{
s= Memo1->Lines->Strings[id];
StringGrid1->
Cells[i][j]=(AnsiString)s;
id++;
}
}
}