Разработка многомодульных интегрированных SDI-приложений (2. Разработка многомодульных приложений)

Посмотреть архив целиком

Разработка многомодульных Windows приложений

Управление формами

Для создания новой программы следует выбрать в меню File – New – Application. Откроется новый проект с пустой формой (Form1). В дальнейшем ее можно переименовать, задав новое значение свойства Name (программное имя формы).

Сохранение проекта следует осуществлять File – Save Project As… . В диалоговом окне можно задать новое имя для модуля формы (вместо Unit1) и для файла проекта (вместо Project1) или оставить имена, предлагаемые системой. Каждое программное приложение следует сохранять в отдельной специально созданной папке.

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

После перечисленных подготовительных действий можно перейти к проектированию главного окна приложения. Открытая форма (Form1) является его макетом. Заголовок окна должен содержать название программы (свойство Caption), главное окно приложения, как правило, может изменять размеры (свойство BorderStyle = bsSizeAble) и содержать меню, отражающее функциональность программы.

Главное окно приложения обычно имеет меню. На рисунке приведен пример формы Form1 приложения, демонстрирующего выполнение вычислительных задач (Caption = “Работа с массивами”). Меню приложения содержит следующие пункты:

Файл (Открыть… – Сохранить… – Разделитель - Выход);

Вычисления (Настройки… - Разделитель - Вычислить)

Сервис (Фон… - Шрифт…)

Помощь (О программе…).


На форме расположены компоненты Label1 (Caption = “Двумерные массивы”), StringGrid1, кнопки Button1 (Caption=”Весь массив”), Button2 (Caption=”По строкам”, Enabled = false) и Button3 (Caption=”По столбцам”, Enabled = false).

Компонент StringGrid позволяет хранить двумерный массив строковых значений, Его свойства: ColCount – количество столбцов (в примере равно 7), RowCount – количество строк (7), FixedCols и FixedRows – количество фиксированных столбцов и строк (по умолчанию 1), DefaultColWidth (82)- ширина столбца и DefaultRowHeight - высота строки в пикселях, принимаемые по умолчанию (применяются при начальной инициализации таблицы).

Векторное свойство StringGrid1->Cells [Acol] [ARow] (ACol – номер столбца, ARow – номер строки) позволяет осуществить доступ к ячейкам массива. Для разрешения редактирования значений таблицы во время работы свойство Options.goEdit должно быть равно true.

Вспомогательные формы

Кроме главной формы приложение может содержать вспомогательные формы. Для добавления новой формы используется меню File – New – Form. Если окно не будет изменять размер, то свойство BorderStyle=bsSingle или bsDialog (специально для диалоговых окон). Для сохранения модуля новой формы можно воспользоваться командой File – Save As… и также при желании изменить его название (свойство Name). На рисунке представлено диалоговое окно (Name=Form5, например, а заголовок Caption = “Настройки вычислений”), позволяющее указать производимые вычисления.



В инструментальной среде Builder C++ можно воспользоваться меню Options | Project… и с помощью диалогового окна Project Options (вкладка Forms) определить, каким образом приложение управляет своими окнами. В списке Main Form (Главная форма) можно выбрать главную форму, которая будет отображаться сразу после старта приложения. По умолчанию – это первая форма, которая была определена при проектировании.

Список Auto-create forms содержит формы, которые строятся при старте приложения. По умолчанию в него помещаются все формы, что ускоряет их отображение. Однако при большом количестве форм программа долго загружается и занимает в оперативной памяти много места. Разработчик может поместить часть форм в список Available forms (даже все, за исключением главной формы). Но при этом ему придется программно создавать каждую из форм списка перед ее вызовом.

Это можно сделать следующими способами (динамическое создание формы во время выполнения приложения):

  • С использованием оператора new

Form2= new TForm2(Form1);

  • С использованием метода объекта Application

Application->CreateForm( __classid(TForm2), &Form2);

Следующий оператор удаляет созданную ранее форму:

delete (Form2);

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


Показать форму на экране можно в обычном режиме: Form2-> Show() или в модальном: Form2->ShowModal(), метод Hide() делает форму невидимой. Однако чтобы в программе можно было из одной формы обратиться к компонентам другой формы, необходимо воспользоваться меню File - Include Unit Hdr . Эта команда предложит программисту список разработанных, но еще «невидимых» из данной формы модулей, а после выбора вставит строку #include, например, #includeUnit2.h”.

Завершение приложения осуществляется методом Application->Terminate() из любой формы приложения, для главной формы можно воспользоваться ее методом Close().


Автономные модули

Можно разрабатывать также и автономные модули, не связанные ни с какой формой. Они дают возможность получить доступ к их содержимому не только из разрабатываемого проекта, но и из других, многократно используя в них уже отлаженный код. Это особенно полезно при работе с функциями. При компиляции любого модуля (в том числе и автономного) создается двоичный объектный файл с расширением .obj.

Для создания автономного модуля можно воспользоваться меню File | New Unit или диалоговым окном New Items (из меню File | New… выбрать вкладку New а на ней – Unit). Созданный модуль будет открыт в редакторе кода. Если команду New Unit использовать в открытом проекте, новый модуль будет зарегистрирован в файле проекта

Например, для нашей задачи можно создать такой модуль (Unit2) и разместить в нем вычислительные функции:

#pragma hdrstop

#include "Unit2.h"

extern int n, m;

//------------------

#pragma package(smart_init)

//Функция вычисления среднего арифметического каждой строки

void sr_ar_stroka(float x[6][6], float y[6])

{ int i, j;

for (i=0; i

{ y[i]=0;

for (j=0; j

y[i]=y[i]+x[i][j];

y[i] = y[i]/n;

}

return ;

}

//Ниже должны быть расположены остальные функции

// …

Часто необходимо, чтобы модуль ссылался на код, содержащийся в другом модуле. Тогда требуется включить файл заголовка второго модуля в первый. Для этого модуль открывают в редакторе кода и применяют команду File | Include Unit Hdr… , также как ранее это делалось для вспомогательных форм.

В нашем примере оператор #includeUnit2.h следует добавить к модулю главной формы приложения (Unit1). Также в Unit1.cpp должен быть добавлен оператор описания и инициализации переменных n и m, которые видны в обоих модулях и определяют размерность двумерного массива: extern int n=6, m=6;


Стандартные диалоговые окна

Windows располагает целым набором стандартных диалогов, которые могут использоваться любым приложением. В распоряжение программиста среда предоставляет компоненты, соответствующие этим диалогам (вкладка Dialogs). Эти компоненты относятся к невизуальным, так как они становятся видны только при выполнении программы.

Применить в приложении стандартное диалоговое окно можно так: поместите в форму компонент, соответствующий диалоговому окну. На форме появится только значок объекта, содержащего свойства диалога. Само окно будет создано только при работе программы в момент вызова диалога с помощью метода Execute().

На вкладке Dialogs всего восемь компонентов: шесть из них модальные, а два – FindDialog и ReplaceDialog – нет. Метод Execute() для этих диалогов создает окно и сразу же возвращает управление программе. Окно продолжает существовать, пока его не закроет пользователь. При необходимости произвести поиск или замену в тексте, вызываются обработчики событий данных компонентов.

Для модального выполнения стандартного диалога в классе TCommonDialog предназначен метод bool Execute(); (возвращает значение true, если пользователь ввел имя файла, и false, если он отказался от ввода).

Вызов метода нужно поместить в обработчике события OnClick соответствующей команды меню. Например, в меню Сервис нашего примера можно настроить цвет фона компонента StringGrid1. Тогда в обработчик команды Сервис – Фон можно поместить следующие операторы:

TColor color;

if (ColorDialog1->Execute())

{

color=ColorDialog1->Color;

StringGrid1->Color=color;

}

Конечно, предварительно на форму необходимо было поместить невизуальный компонента ColorDialog, а при необходимости выбора характеристик шрифта еще и FontDialog. В обработчике команды Сервис - Шрифт разместить код:

if (FontDialog1->Execute())

StringGrid1->Font->Assign(FontDialog1->Font);

В нашем примере также используются диалоги открытия и сохранения файлов (компоненты OpenDialog и SaveDialog). Свойство Filter - список названий и масок шаблонов для выбора файлов можно в данном случае установить так:

Текстовые файлы (*.txt)|*.txt)

Все файлы (*.*)|*.*),

FileName - строка с полным именем выбранного пользователем файла (перед отображением диалога значение этого свойства используется для инициализации текстового редактора с именем файла).

Русифицированное диалоговое окно

Метод 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):


Случайные файлы

Файл
VDV-1197.DOC
24905.rtf
37105.rtf
19749.rtf
130629.rtf




Чтобы не видеть здесь видео-рекламу достаточно стать зарегистрированным пользователем.
Чтобы не видеть никакую рекламу на сайте, нужно стать VIP-пользователем.
Это можно сделать совершенно бесплатно. Читайте подробности тут.