5. Работа с формами в C++Builder

5.1. Создание и уничтожение форм

Окна составляют основу функционирования практически любого приложения Windows. Кроме задачи визуального представления приложения, окно в Windows несет важную функциональную нагрузку – именно функция окна в идеологии работы операционной системы должна обрабатывать все поступающие в окно сообщения. Поэтому форма системы C++Builder является основой любого приложения. При создании нового проекта (пункт меню File | New | Application) форма добавляется в проект автоматически. Большинство приложений используют несколько окон. Включение в проект новой формы осуществляется командой File | New Form или командой File | New | Other с последующим выбором формы в Хранилище, например, из вкладок Forms или Dialogs. По умолчанию все формы создаются автоматически при запуске приложения, и первая из вве­денных в приложение форм считается главной [1]. Главная форма отличается от прочих рядом свойств. Во-первых, именно этой форме передается управление в начале выполнения приложения. Во-вторых, закрытие пользователем главной формы означает за­вершение выполнения приложения. В-третьих, существуют специальные соглашения о порядке скрытия главной формы, о них говорилось в главе 4.2.

У программиста существует возможность изменения порядка создания форм. Он может объявить главной любую из форм, включенных в проект. Создание всех форм приложения при его запуске зачастую будет очень неэффективным с точки зрения расходования памяти. Если некоторое окно должно вызываться в определенный момент работы программы по команде пользователя на короткий срок (например, диалоговое окно для изменения параметров системы), то хранить это окно все время работы программы, просто не отображая его на экране, будет очень неэффективным подходом. Для приложений, работающих в многооконном режиме (MDI) вообще неизвестно заранее, сколько окон одновременно захочет открыть пользователь при работе с программой.

НЕ нашли? Не то? Что вы ищете?

Изменить принятые по умолчанию условия относительно форм можно в окне опций проекта, которое вызывается командой Project | Options главного меню. В открывшемся окне свойств проекта (Project Options) среди прочих есть закладка Forms, которая определяет свойства добавленных в проект форм (рис 5.1).

Рисунок 5.1 – Окно свойств проекта, закладка «Формы»

В этом окне можно определить, будет ли та или иная форма создаваться автоматически (в этом случае ее название необходимо поместить в левый список Auto-create forms) или будет доступной для создания уже в момент работы программы (правый список, Available forms). Здесь же определяется, какая из форм будет считаться главной в приложении (Main form). Главной может быть только форма из левого списка.

Согласно уже описанной выше технологии двунаправленной разработки, сделанные в окне свойств проекта изменения приводят к изменению кода программы. Действительно, если посмотреть на содержимое основного файла проекта (Project1.cpp), то можно увидеть эти изменения. Во-первых, для каждой добавленной в проект формы вставляется вызов макроса USEFORM. Назначение этого макроса – подключение файла с кодом формы к проекту. Вызов макроса для формы Form1, например, будет выглядеть следующим образом:

USEFORM("Unit1.cpp", Form1);

Первый параметр макроса содержит имя файла модуля, соответствующего форме (например, "Unit1.cpp"), а второй параметр — имя формы.

Помимо этого, в текст программы добавляются команды создания тех форм, которые определены в проекте как автоматически создаваемые. Эти команды реализуются как вызовы метода CreateForm объекта Application:

Application->CreateForm(__classid(TForm4), &Form4);

Application->CreateForm(__classid(TForm3), &Form3);

При этом создание главной формы (для нашего примера – Form4) производится первым. Остальные формы (Form1, Form2) в момент запуска программы не создаются, но программист может в любой момент создать их, вызвав метод CreateForm. Например, из файла модуля третьей или четвертой формы можно создать форму Form2 при помощи следующего вызова:

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

Такой вызов не сработает, если не предпринять дополнительных действий. Дело в том, что файлы каждой формы обособлены, и для файла Unit3.cpp, в котором мы предположительно создаем новую форму, класс TForm2 и указатель Form2 неизвестны, в связи с чем возникнет ошибка на этапе его компиляции. Решением является подключение к файлу unit3.cpp заголовочного файла второй формы, то есть добавление строки

#include “Unit2.cpp”

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

После создания формы в нее приходит ряд стандартных сообщений Windows, которые соответствую различным стадиям формирования окна – создание объекта «окно» в памяти, отображение окна, установка размеров окна, отображение клиентской области окна. Для формы программы, написанной в C++Builder, эти сообщения проявляются в виде событий. Перечень событий в порядке их возникновения в форме можно посмотреть в таблице 5.1.

Таблица 5.1.

События, возникающие при создании формы

Событие

Описание

OnCreate

создание формы и всех ее компонент

OnShow

отображение формы на экране

Продолжение таблицы 5.1.

OnActivate

фокус ввода передается форме

OnEnter

фокус передается компоненту формы, первому в последовательности та­буляции

OnResize

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

On Paint

прорисовка клиентской области формы

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

Событие OnShow возникает, когда форма отображается на экране либо при создании, либо при вызове методов Show и ShowModal. Скрыть форму можно методом Hide, при этом возникает событие OnHide.

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

void __fastcall TForm1::FormCloseQuery(TObject *Sender,

bool &CanClose);

Первый параметр, как и для большинства событий, передает адрес компонента-источника события. Второй параметр, являясь логическим по типу, может принимать значения true и false, причем, так как он определен в виде ссылки, присвоенное ему значение будет выходным. В обработчике события OnCloseQuery принимается решение – разрешить или нет процедуру закрытия окна. Это решение может быть принято по текущему состоянию приложения, по запросу разрешения у пользователя, каким либо иным способом, но оформляется оно путем присвоения значения параметру CanClose: если присвоить ему true, то процесс закрытия окна разрешается, если false – запрещается. По умолчанию параметру CanClose присваивается истинное значение. Следующий пример иллюстрирует, как реализовать запрос на разрешение закрытия программы у пользователя:

void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)

{

if(MessageBox(NULL,"Действительно закрыть окно","Внимание!", MB_OKCANCEL)!=IDOK)

CanClose=false;

}

Если в обработчике события OnCloseQuery разрешено закрытие окна или этому событию вообще не сопоставлен обработчик, то возникает событие OnClose. При срабатывании этого события форма по-прежнему отображена на экране, поэтому отменить закрытие можно и в обработчике OnClose. Прототип обработчика OnClose выглядит следующим образом:

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)

Здесь особого внимания заслуживает параметр Action, который также является ссылкой, а потому – выходным параметром функции-обработчика.

Параметр Action может принимать следующие значения:

caNone - не закрывать форму;

caHide - сделать форму невидимой;

caMinimize - свернуть форму в пиктограмму на панели задач;

caFree - уничтожить форму.

Если в обработчике события OnClose присвоить параметру значение caNone, то процедура закрытия окна будет прекращена, и оно останется на экране в прежнем виде. В связи с этим пример с подтверждением закрытия окна пользователя можно перенести в обработчик OnClose:

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)

{

if(MessageBox(NULL,"Действительно закрыть окно","Внимание!", MB_OKCANCEL)!=IDOK)

Action=caNone

}

Если параметру Action присвоить значение caHide, то окно станет невидимым, при этом оно по-прежнему будет находиться в памяти, его свойства, свойства компонент формы будут доступны. Окно можно сделать видимым, вызвав, например, метод Show. Необходимо отметить, что параметр Action по умолчанию принимает значение caHide для всех окон, стиль которых в свойстве FormStyle задан не как fsMDIForm или fsMDIChild. Поэтому, если необходимо уничтожить такое окно, для него недостаточно просто вызвать метод Close, потому что окно скроется на экране, но будет оставаться в памяти. Выходом здесь может стать либо добавление для формы обработчика события OnClose с обработчиком вида Action=caFree, либо удаление формы после вызова метода Close стандартной операцией delete (последнее замечание не относится к главной форме приложения, которая удаляется при вызове метода Close).

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14