SlideShare a Scribd company logo
1 of 10
Download to read offline
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
1
Лекция 11 (ч.6)
Синтаксис и программные конструкции Visual C
5. Работа с формами в C++Builder
5.1. Создание и уничтожение форм
Окна составляют основу функционирования практически любого приложения Windows.
Кроме задачи визуального представления приложения, окно в Windows несет важную
функциональную нагрузку – именно функция окна в идеологии работы операционной системы
должна обрабатывать все поступающие в окно сообщения. Поэтому форма системы C++Builder
является основой любого приложения. При создании нового проекта (пункт меню File | New |
Application) форма добавляется в проект автоматически. Большинство приложений используют
несколько окон. Включение в проект новой формы осуществляется командой File | New Form или
командой File | New | Other с последующим выбором формы в Хранилище, например, из вкладок
Forms или Dialogs. По умолчанию все формы создаются автоматически при запуске приложения, и
первая из введенных в приложение форм считается главной [1]. Главная форма отличается от
прочих рядом свойств. Во-первых, именно этой форме передается управление в начале
выполнения приложения. Во-вторых, закрытие пользователем главной формы означает за-
вершение выполнения приложения. В-третьих, существуют специальные соглашения о порядке
скрытия главной формы.
У программиста существует возможность изменения порядка создания форм. Он может
объявить главной любую из форм, включенных в проект. Создание всех форм приложения при
его запуске зачастую будет очень неэффективным с точки зрения расходования памяти. Если
некоторое окно должно вызываться в определенный момент работы программы по команде
пользователя на короткий срок (например, диалоговое окно для изменения параметров системы),
то хранить это окно все время работы программы, просто не отображая его на экране, будет очень
неэффективным подходом. Для приложений, работающих в многооконном режиме (MDI) вообще
неизвестно заранее, сколько окон одновременно захочет открыть пользователь при работе с
программой.
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
2
Изменить принятые по умолчанию условия относительно форм можно в окне опций
проекта, которое вызывается командой Project | Options главного меню. В открывшемся окне
свойств проекта (Project Options) среди прочих есть закладка Forms, которая определяет свойства
добавленных в проект форм (рис 5.1).
Рисунок 5.1 – Окно свойств проекта, закладка «Формы»
В этом окне можно определить, будет ли та или иная форма создаваться автоматически (в этом
случае ее название необходимо поместить в левый список Auto-create forms) или будет доступной для
создания уже в момент работы программы (правый список, Available forms). Здесь же определяется,
какая из форм будет считаться главной в приложении (Main form). Главной может быть только форма
из левого списка.
Согласно уже описанной выше технологии двунаправленной разработки, сделанные в окне
свойств проекта изменения приводят к изменению кода программы. Действительно, если посмотреть на
содержимое основного файла проекта (Project1.cpp), то можно увидеть эти изменения. Во-первых, для
каждой добавленной в проект формы вставляется вызов макроса USEFORM. Назначение этого макроса
– подключение файла с кодом формы к проекту. Вызов макроса для формы Form1, например, будет
выглядеть следующим образом:
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
3
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, которые
соответствую различным стадиям формирования окна – создание объекта «окно» в памяти,
отображение окна, установка размеров окна, отображение клиентской области окна. Для формы
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
4
программы, написанной в C++Builder, эти сообщения проявляются в виде событий. Перечень
событий в порядке их возникновения в форме можно посмотреть в таблице 5.1.
Таблица 5.1.
События, возникающие при создании формы
Событие Описание
OnCreate создание формы и всех ее компонент
OnShow отображение формы на экране
OnActivate фокус ввода передается форме
OnEnter фокус передается компоненту формы, первому в
последовательности табуляции
OnResize переустанавливаются размеры формы
On Paint прорисовка клиентской области формы
В отличие от остальных событий в таблице, событие OnCreate возникает однократно для
каждой формы. Это происходит в момент ее создания, когда ни один компонент формы, ни
сама она еще не отображены на экране. Этот факт позволяет программистам в обработчике
события OnCreate осуществлять начальную настройку как свойств самой формы, так и
входящих в нее компонент. При этом, если свойство OldCreateOrder формы установлена в false,
то событие OnCreate возникнет после окончания работы конструкторов всех компонентов
формы.
Событие OnShow возникает, когда форма отображается на экране либо при создании,
либо при вызове методов Show и ShowModal. Скрыть форму можно методом Hide, при этом
возникает событие OnHide.
В любой момент форму можно закрыть, для этого используется метод Close. При этом
форма не закрывается автоматически, а происходит каскадный вызов последовательности
обработчиков событий, который позволяет программисту реализовать для пользователя
возможность отмены команды закрытия окна. Первым при обработке команды Close возникает
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
5
событие 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 может принимать следующие значения:
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
6
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).
Присвоение параметру Action значения caMinimize приводит к сворачиванию окна в
пиктограмму. Это значение присваивается по умолчанию для дочерних MDI-окон.
Если же параметру Action присвоить значение caFree, то будет разрешено удаление
формы. После этого процесс удаления формы становится необратимым, для формы сработает
еще одно событие OnDestroy. В момент возникновения этого события окно уже невидимо на
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
7
экране, отменить его уничтожение невозможно, основное назначение обработчика события
OnDestroy – корректное завершение работы формы, очистка памяти от объектов, ею
использовавшихся. Уничтожить форму можно, минуя последовательность событий
OnCloseQuery, OnClose, OnDestory. Если вызвать для формы метод Free или уничтожать ее
операцией delete, то сразу возникает событие OnDestroy и форма удалится из памяти.
5.2. Модальный режим работы форм
Если отобразить форму методом ShowModal, то она будет работать в модальном режиме.
Модальный режим означает, что весь фокус ввода в приложении сосредоточен на данной форме,
и пользователь не сможет работать с другими формами приложения, пока не закроет модальное
окно. Фактически, для модального окна система создает свою очередь сообщений, и все
сообщения приложения приходят только в это окно. Модальный режим чаще всего используется
для диалоговых окон, в которых задаются параметры работы системы. Необходимо также
отметить, что модальность – это режим работы окна, а не какое-то его свойство, которое
необходимо определить для него при проектировании. Одна и та же форма может быть
отображена как в нормальном режиме (методом Show), так и в модальном (методом ShowModal).
Работа модального окна отличается от обычного окна только способом закрытия окна. За
закрытие модального окна отвечает свойство ModalResult. Первоначально это свойство хранит
нулевое значение. Изменение значения этого свойства (присвоение ему ненулевого значения)
приводит к закрытию формы. Всего для свойства ModalResult предусмотрено 11 различных
значений от 0 до 10 (в C++Builder 6). Перечень этих значений приведен в таблице 5.2.
Таблица 5.2.
Возможные значения свойства ModalResult формы
Константа С++Builder Знач. Для чего используется
mrNone 0 Значение по умолчанию
mrOk (idOk) 1 Форма закрыта нажатием кнопки Ok
mrCancel (idCancel) 2 Форма закрыта кнопкой Cancel, вызовом метода Close
либо кнопкой закрытия в заголовке окна
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
8
mrAbort (idAbort) 3 Форма закрыта нажатием кнопки Abort
mrRetry (idRetry) 4 Форма закрыта нажатием кнопки Retry
mrIgnore (idIgnore) 5 Форма закрыта нажатием кнопки Ignore
mrYes (idYes) 6 Форма закрыта нажатием кнопки Yes
mrNo (idNo) 7 Форма закрыта нажатием кнопки No
mrAll (idAll) 8 Форма закрыта нажатием кнопки All
mrNoToAll (idNoToAll) 9 Форма закрыта нажатием кнопки NoToAll
mrYesToAll (idYesToAll) 10 Форма закрыта нажатием кнопки YesToAll
Таким образом, присвоение ModalResult значения от 1 до 10 имитирует нажатие одной из
кнопок закрытия окна из стандартного набора Windows. Окно, создавшее модальную форму,
может узнать, каким образом было закрыто окно. Для этого необходимо сравнить результат,
возвращаемый функцией ShowModal, с константами из таблицы 5.2 (этот метод, очевидно,
прерывает работу кода до момента закрытия модального окна):
Application->CreateForm(__classid(TForm2), &Form2);
int mr=Form2->ShowModal();
if(mr==mrOk)
{MessageBox(NULL,"Окно закрыто нажатием кнопки ОК","Внимание",MB_OK);
//работа с компонентами формы Form2, измененными пользова
//телем при работе с ней в модальном режиме
}
delete Form2;
В коде формы Form2 необходимо в таком случае в тот момент, когда требуется закрыть
форму, выполнить присваивание ModalResult=mrOk. Альтернативным вариантом является
использование свойства ModalResult кнопок типа TButton или TBitBtn. Задав для этого свойства
кнопки на форме одно из значений из таблицы 5.2, программист определит, что при нажатии
этой кнопки окно закроется, и статус закрытия будет совпадать со значением свойства
ModalResult кнопки.
5.3. Многодокументный интерфейс (MDI)
Многие современные приложения поддерживают многооконный режим работы, когда в
каждом окне осуществляется работа с отдельным документом. Подобный интерфейс имеет
устоявшийся протокол взаимодействия окон, когда одно из окон является главным, а остальные –
дочерними. Назначение главного окна – управлять дочерними окнами, меню этого окна обычно
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
9
содержит команды создания, удаления дочерних окон, изменения порядка их расположения в
клиентской области главного окна. Закрытие родительского окна ведет к завершению работы
всего приложения. Дочерние окна предназначены для отображения редактируемого документа. В
помощь программисту для реализации подобного интерфейса приложения Windows
поддерживает спецификацию MDI (Multiple Document Interface). На уровне операционной
системы MDI поддерживается специальным набором API-функций и сообщений. Для
программиста на C++Builder MDI интерфейс доступен как набор свойств и методов все того же
компонента TForm.
Для того, чтобы объявить форму родительской MDI-формой, необходимо присвоить ее
свойству FormStyle значение fsMDIForm. Для дочерней формы это свойство необходимо
установить в fsMDIChild. Дочернюю форму необходимо отнести к доступным для создания
формам (рис. 5.1), поскольку дочерние окна должны создаваться пользователем в процессе
работы программы. Тогда код создания дочерней формы должен выглядеть следующим образом:
void __fastcall TForm1::new1Click(TObject *Sender)
{
TForm2 *child=new TForm2(Application);
child->Show();
}
Для управления созданными дочерними окнами можно использовать несколько свойств и
методов. Прежде всего, необходимо обратить внимание на массив MDIChildren, который для
главной MDI-формы хранит адреса всех существующих на данный момент дочерних окон. При
этом количество дочерних окон можно получить из свойства MDIChildCount. Адрес активной
дочерней формы хранится в свойстве ActiveMDIChild. Пример переименования всех дочерних
окон приведен в следующем листинге:
for(i=0;i<MDIChildCount;i++)
MDIChildren[i]->Caption="Window"+IntToStr(i+1);
Порядок расположения дочерних окон в клиентской области родительского окна можно
изменять вызовами методов Tile и Cascade для главной формы. Метод Tile выстраивает дочерние
окна рядом друг с другом, в зависимости от значения свойства TileMode они выстраиваются по
горизонтали (tbHorizontal) или по вертикали (tbVertical). Метод Cascade выстраивает дочерние
Лекция №11 для дисциплин: «Прикладное программирование» и «Языки
программирования»
10
окна каскадом. Для упорядочивания свернутых в пиктограмму дочерних окон в клиентской
области родительского окна используется метод ArrangeIcons.
Особенностью работы дочерних MDI-окон является то, что при закрытии их методом
Close или нажатием кнопки закрытия окна в его заголовке они по умолчанию сворачиваются в
пиктограмму, а не закрываются. Закрываться они будут только если в обработчике события
OnClose дочернего MDI-окна присваивать параметру Action значения caFree или caHide.
Еще одна особенность взаимодействия родительского и дочерних MDI-окон –
встраивание меню дочернего окна в состав родительского. Если для дочернего окна
спроектировано меню (чаще всего оно включает команды для работы с документом), то оно
будет встроено в меню родительского окна (которое обычно содержит команды управления
окнами). Порядок следования пунктов меню дочернего окна в родительском меню, а,
следовательно, и место встраивания меню дочернего окна определяется значением свойства
GroupIndex каждого раздела меню. Именно поэтому, если не изменять значения свойства
GroupIndex у меню родительского и дочернего окна, то в процессе работы второе может
подменять собой первое, что является очень распространенной ошибкой начинающих
программистов. Это происходит потому, что их свойствам GroupIndex по умолчанию
присваиваются одинаковые значения, и при появлении дочернего окна его меню встраивается на
те же позиции, которые должны занимать пункты родительского меню. Задача программиста –
следить, чтобы пункты меню родительского и дочернего окон имели различные значения
свойства GroupIndex.
Вывод
Форма является основным компонентом в проекте приложения на C++Builder, что
обусловлено особенной ролью окна в ОС Windows. Формы C++Builder реализуются на основе
класса TForm, который позволяет программисту отслеживать основные стадии работы окна:
создание, отображение, перерисовка, закрытие, уничтожение, а также управлять окном и его
подчиненными элементами. Для форм предусмотрены модальный и немодальный режимы
отображения. Окно в модальном режиме фокусирует на себя весь ввод информации в
приложение. Если приложение должно работать в многодокументном режиме, то для него можно
использовать специальный MDI-интерфейс, который поддерживается классом TForm.

More Related Content

Viewers also liked (14)

4.modül
4.modül4.modül
4.modül
 
философия
философияфилософия
философия
 
неделя здоровья в детском саду №39
неделя здоровья в детском саду №39неделя здоровья в детском саду №39
неделя здоровья в детском саду №39
 
Frente integral
Frente integralFrente integral
Frente integral
 
Presentation2
Presentation2Presentation2
Presentation2
 
урок
урокурок
урок
 
жимсээ
жимсээжимсээ
жимсээ
 
отчёт за сентябрь
отчёт за сентябрьотчёт за сентябрь
отчёт за сентябрь
 
содоклад е.в. бербер
содоклад е.в. берберсодоклад е.в. бербер
содоклад е.в. бербер
 
Personas workshop | Discovering "The User"
Personas workshop | Discovering "The User"Personas workshop | Discovering "The User"
Personas workshop | Discovering "The User"
 
Herramientas tic para publicar
Herramientas tic para publicarHerramientas tic para publicar
Herramientas tic para publicar
 
Contibuto argos pallavolo
Contibuto argos pallavoloContibuto argos pallavolo
Contibuto argos pallavolo
 
Diari del 16 de juny de 2015
Diari del 16 de juny de 2015Diari del 16 de juny de 2015
Diari del 16 de juny de 2015
 
ферменты
ферментыферменты
ферменты
 

Similar to лек11 6

Разработка оптимального ПО - создание раскадровок и сбор отзывов от заинтерес...
Разработка оптимального ПО - создание раскадровок и сбор отзывов от заинтерес...Разработка оптимального ПО - создание раскадровок и сбор отзывов от заинтерес...
Разработка оптимального ПО - создание раскадровок и сбор отзывов от заинтерес...
Александр Шамрай
 
упражнение 6
упражнение 6упражнение 6
упражнение 6
Artyukhova
 
работа в объектно ориентированной среде Delphi
работа в объектно ориентированной среде Delphiработа в объектно ориентированной среде Delphi
работа в объектно ориентированной среде Delphi
BaurjanZhalmagambetov
 
Изучение кода с использованием инструментов архитектуры в Visual Studio Ultim...
Изучение кода с использованием инструментов архитектуры в Visual Studio Ultim...Изучение кода с использованием инструментов архитектуры в Visual Studio Ultim...
Изучение кода с использованием инструментов архитектуры в Visual Studio Ultim...
Александр Шамрай
 
Отладка с использованием Intelli Trace в Visual Studio Ultimate 2012
Отладка с использованием Intelli Trace в Visual Studio Ultimate 2012Отладка с использованием Intelli Trace в Visual Studio Ultimate 2012
Отладка с использованием Intelli Trace в Visual Studio Ultimate 2012
Александр Шамрай
 
отладка Mpi приложений
отладка Mpi приложенийотладка Mpi приложений
отладка Mpi приложений
Michael Karpov
 

Similar to лек11 6 (20)

создание приложений windows forms
создание приложений windows formsсоздание приложений windows forms
создание приложений windows forms
 
лек11 4
лек11 4лек11 4
лек11 4
 
C# Desktop. Занятие 08.
C# Desktop. Занятие 08.C# Desktop. Занятие 08.
C# Desktop. Занятие 08.
 
Инструкция
Инструкция Инструкция
Инструкция
 
лек11 7
лек11 7лек11 7
лек11 7
 
лек11 7
лек11 7лек11 7
лек11 7
 
Разработка оптимального ПО - создание раскадровок и сбор отзывов от заинтерес...
Разработка оптимального ПО - создание раскадровок и сбор отзывов от заинтерес...Разработка оптимального ПО - создание раскадровок и сбор отзывов от заинтерес...
Разработка оптимального ПО - создание раскадровок и сбор отзывов от заинтерес...
 
лек11 3
лек11 3лек11 3
лек11 3
 
B pwin&ramus
B pwin&ramusB pwin&ramus
B pwin&ramus
 
упражнение 6
упражнение 6упражнение 6
упражнение 6
 
работа в объектно ориентированной среде Delphi
работа в объектно ориентированной среде Delphiработа в объектно ориентированной среде Delphi
работа в объектно ориентированной среде Delphi
 
VAMR ACADEMY Второе занятие
VAMR ACADEMY Второе занятиеVAMR ACADEMY Второе занятие
VAMR ACADEMY Второе занятие
 
Шичко И. Вопросы практического применения СУБД FileMaker при решении повседне...
Шичко И. Вопросы практического применения СУБД FileMaker при решении повседне...Шичко И. Вопросы практического применения СУБД FileMaker при решении повседне...
Шичко И. Вопросы практического применения СУБД FileMaker при решении повседне...
 
Изучение кода с использованием инструментов архитектуры в Visual Studio Ultim...
Изучение кода с использованием инструментов архитектуры в Visual Studio Ultim...Изучение кода с использованием инструментов архитектуры в Visual Studio Ultim...
Изучение кода с использованием инструментов архитектуры в Visual Studio Ultim...
 
Enterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russianEnterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russian
 
Отладка с использованием Intelli Trace в Visual Studio Ultimate 2012
Отладка с использованием Intelli Trace в Visual Studio Ultimate 2012Отладка с использованием Intelli Trace в Visual Studio Ultimate 2012
Отладка с использованием Intelli Trace в Visual Studio Ultimate 2012
 
отладка Mpi приложений
отладка Mpi приложенийотладка Mpi приложений
отладка Mpi приложений
 
26 27_28_29_30_процедуры и тригеры
26  27_28_29_30_процедуры и тригеры26  27_28_29_30_процедуры и тригеры
26 27_28_29_30_процедуры и тригеры
 
лек11 2
лек11 2лек11 2
лек11 2
 
Lecture 11 1
Lecture 11 1Lecture 11 1
Lecture 11 1
 

More from Anastasia Snegina

птп по ппп 2013 2014
птп по ппп 2013 2014 птп по ппп 2013 2014
птп по ппп 2013 2014
Anastasia Snegina
 
прикл.прогр птп 13 14
прикл.прогр птп 13 14прикл.прогр птп 13 14
прикл.прогр птп 13 14
Anastasia Snegina
 
2012 2013 пм спп провидошина
2012 2013  пм спп провидошина2012 2013  пм спп провидошина
2012 2013 пм спп провидошина
Anastasia Snegina
 
2012 2013 пм спп провидошина
2012 2013  пм спп провидошина2012 2013  пм спп провидошина
2012 2013 пм спп провидошина
Anastasia Snegina
 
рп по у пп практике в
рп по у пп практике врп по у пп практике в
рп по у пп практике в
Anastasia Snegina
 
рп по пр практике в
рп по пр практике врп по пр практике в
рп по пр практике в
Anastasia Snegina
 
рп по у сп практике в
рп по у сп практике врп по у сп практике в
рп по у сп практике в
Anastasia Snegina
 
рп по у пп практике вт
рп по у пп практике втрп по у пп практике вт
рп по у пп практике вт
Anastasia Snegina
 
рп по пр практике вт
рп по пр практике втрп по пр практике вт
рп по пр практике вт
Anastasia Snegina
 
рп по у сп практике вт
рп по у сп практике втрп по у сп практике вт
рп по у сп практике вт
Anastasia Snegina
 
рп по у пп практике вт
рп по у пп практике втрп по у пп практике вт
рп по у пп практике вт
Anastasia Snegina
 
рп по пр практике вт
рп по пр практике втрп по пр практике вт
рп по пр практике вт
Anastasia Snegina
 
рп по у сп практике вт
рп по у сп практике втрп по у сп практике вт
рп по у сп практике вт
Anastasia Snegina
 

More from Anastasia Snegina (20)

птп по ппп 2013 2014
птп по ппп 2013 2014 птп по ппп 2013 2014
птп по ппп 2013 2014
 
прикл.прогр птп 13 14
прикл.прогр птп 13 14прикл.прогр птп 13 14
прикл.прогр птп 13 14
 
я.прогр птп
я.прогр птпя.прогр птп
я.прогр птп
 
пп кос вт
пп кос втпп кос вт
пп кос вт
 
пп кос в
пп кос впп кос в
пп кос в
 
пп кос в
пп кос впп кос в
пп кос в
 
2012 2013 пм спп провидошина
2012 2013  пм спп провидошина2012 2013  пм спп провидошина
2012 2013 пм спп провидошина
 
2012 2013 пм спп провидошина
2012 2013  пм спп провидошина2012 2013  пм спп провидошина
2012 2013 пм спп провидошина
 
пп кос вт
пп кос втпп кос вт
пп кос вт
 
рп по у пп практике в
рп по у пп практике врп по у пп практике в
рп по у пп практике в
 
рп по пр практике в
рп по пр практике врп по пр практике в
рп по пр практике в
 
рп по у сп практике в
рп по у сп практике врп по у сп практике в
рп по у сп практике в
 
рп по у пп практике вт
рп по у пп практике втрп по у пп практике вт
рп по у пп практике вт
 
рп по пр практике вт
рп по пр практике втрп по пр практике вт
рп по пр практике вт
 
рп по у сп практике вт
рп по у сп практике втрп по у сп практике вт
рп по у сп практике вт
 
рп по у пп практике вт
рп по у пп практике втрп по у пп практике вт
рп по у пп практике вт
 
рп по пр практике вт
рп по пр практике втрп по пр практике вт
рп по пр практике вт
 
рп по у сп практике вт
рп по у сп практике втрп по у сп практике вт
рп по у сп практике вт
 
лр18
лр18лр18
лр18
 
лр15
лр15лр15
лр15
 

лек11 6

  • 1. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 1 Лекция 11 (ч.6) Синтаксис и программные конструкции Visual C 5. Работа с формами в C++Builder 5.1. Создание и уничтожение форм Окна составляют основу функционирования практически любого приложения Windows. Кроме задачи визуального представления приложения, окно в Windows несет важную функциональную нагрузку – именно функция окна в идеологии работы операционной системы должна обрабатывать все поступающие в окно сообщения. Поэтому форма системы C++Builder является основой любого приложения. При создании нового проекта (пункт меню File | New | Application) форма добавляется в проект автоматически. Большинство приложений используют несколько окон. Включение в проект новой формы осуществляется командой File | New Form или командой File | New | Other с последующим выбором формы в Хранилище, например, из вкладок Forms или Dialogs. По умолчанию все формы создаются автоматически при запуске приложения, и первая из введенных в приложение форм считается главной [1]. Главная форма отличается от прочих рядом свойств. Во-первых, именно этой форме передается управление в начале выполнения приложения. Во-вторых, закрытие пользователем главной формы означает за- вершение выполнения приложения. В-третьих, существуют специальные соглашения о порядке скрытия главной формы. У программиста существует возможность изменения порядка создания форм. Он может объявить главной любую из форм, включенных в проект. Создание всех форм приложения при его запуске зачастую будет очень неэффективным с точки зрения расходования памяти. Если некоторое окно должно вызываться в определенный момент работы программы по команде пользователя на короткий срок (например, диалоговое окно для изменения параметров системы), то хранить это окно все время работы программы, просто не отображая его на экране, будет очень неэффективным подходом. Для приложений, работающих в многооконном режиме (MDI) вообще неизвестно заранее, сколько окон одновременно захочет открыть пользователь при работе с программой.
  • 2. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 2 Изменить принятые по умолчанию условия относительно форм можно в окне опций проекта, которое вызывается командой Project | Options главного меню. В открывшемся окне свойств проекта (Project Options) среди прочих есть закладка Forms, которая определяет свойства добавленных в проект форм (рис 5.1). Рисунок 5.1 – Окно свойств проекта, закладка «Формы» В этом окне можно определить, будет ли та или иная форма создаваться автоматически (в этом случае ее название необходимо поместить в левый список Auto-create forms) или будет доступной для создания уже в момент работы программы (правый список, Available forms). Здесь же определяется, какая из форм будет считаться главной в приложении (Main form). Главной может быть только форма из левого списка. Согласно уже описанной выше технологии двунаправленной разработки, сделанные в окне свойств проекта изменения приводят к изменению кода программы. Действительно, если посмотреть на содержимое основного файла проекта (Project1.cpp), то можно увидеть эти изменения. Во-первых, для каждой добавленной в проект формы вставляется вызов макроса USEFORM. Назначение этого макроса – подключение файла с кодом формы к проекту. Вызов макроса для формы Form1, например, будет выглядеть следующим образом:
  • 3. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 3 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, которые соответствую различным стадиям формирования окна – создание объекта «окно» в памяти, отображение окна, установка размеров окна, отображение клиентской области окна. Для формы
  • 4. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 4 программы, написанной в C++Builder, эти сообщения проявляются в виде событий. Перечень событий в порядке их возникновения в форме можно посмотреть в таблице 5.1. Таблица 5.1. События, возникающие при создании формы Событие Описание OnCreate создание формы и всех ее компонент OnShow отображение формы на экране OnActivate фокус ввода передается форме OnEnter фокус передается компоненту формы, первому в последовательности табуляции OnResize переустанавливаются размеры формы On Paint прорисовка клиентской области формы В отличие от остальных событий в таблице, событие OnCreate возникает однократно для каждой формы. Это происходит в момент ее создания, когда ни один компонент формы, ни сама она еще не отображены на экране. Этот факт позволяет программистам в обработчике события OnCreate осуществлять начальную настройку как свойств самой формы, так и входящих в нее компонент. При этом, если свойство OldCreateOrder формы установлена в false, то событие OnCreate возникнет после окончания работы конструкторов всех компонентов формы. Событие OnShow возникает, когда форма отображается на экране либо при создании, либо при вызове методов Show и ShowModal. Скрыть форму можно методом Hide, при этом возникает событие OnHide. В любой момент форму можно закрыть, для этого используется метод Close. При этом форма не закрывается автоматически, а происходит каскадный вызов последовательности обработчиков событий, который позволяет программисту реализовать для пользователя возможность отмены команды закрытия окна. Первым при обработке команды Close возникает
  • 5. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 5 событие 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 может принимать следующие значения:
  • 6. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 6 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). Присвоение параметру Action значения caMinimize приводит к сворачиванию окна в пиктограмму. Это значение присваивается по умолчанию для дочерних MDI-окон. Если же параметру Action присвоить значение caFree, то будет разрешено удаление формы. После этого процесс удаления формы становится необратимым, для формы сработает еще одно событие OnDestroy. В момент возникновения этого события окно уже невидимо на
  • 7. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 7 экране, отменить его уничтожение невозможно, основное назначение обработчика события OnDestroy – корректное завершение работы формы, очистка памяти от объектов, ею использовавшихся. Уничтожить форму можно, минуя последовательность событий OnCloseQuery, OnClose, OnDestory. Если вызвать для формы метод Free или уничтожать ее операцией delete, то сразу возникает событие OnDestroy и форма удалится из памяти. 5.2. Модальный режим работы форм Если отобразить форму методом ShowModal, то она будет работать в модальном режиме. Модальный режим означает, что весь фокус ввода в приложении сосредоточен на данной форме, и пользователь не сможет работать с другими формами приложения, пока не закроет модальное окно. Фактически, для модального окна система создает свою очередь сообщений, и все сообщения приложения приходят только в это окно. Модальный режим чаще всего используется для диалоговых окон, в которых задаются параметры работы системы. Необходимо также отметить, что модальность – это режим работы окна, а не какое-то его свойство, которое необходимо определить для него при проектировании. Одна и та же форма может быть отображена как в нормальном режиме (методом Show), так и в модальном (методом ShowModal). Работа модального окна отличается от обычного окна только способом закрытия окна. За закрытие модального окна отвечает свойство ModalResult. Первоначально это свойство хранит нулевое значение. Изменение значения этого свойства (присвоение ему ненулевого значения) приводит к закрытию формы. Всего для свойства ModalResult предусмотрено 11 различных значений от 0 до 10 (в C++Builder 6). Перечень этих значений приведен в таблице 5.2. Таблица 5.2. Возможные значения свойства ModalResult формы Константа С++Builder Знач. Для чего используется mrNone 0 Значение по умолчанию mrOk (idOk) 1 Форма закрыта нажатием кнопки Ok mrCancel (idCancel) 2 Форма закрыта кнопкой Cancel, вызовом метода Close либо кнопкой закрытия в заголовке окна
  • 8. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 8 mrAbort (idAbort) 3 Форма закрыта нажатием кнопки Abort mrRetry (idRetry) 4 Форма закрыта нажатием кнопки Retry mrIgnore (idIgnore) 5 Форма закрыта нажатием кнопки Ignore mrYes (idYes) 6 Форма закрыта нажатием кнопки Yes mrNo (idNo) 7 Форма закрыта нажатием кнопки No mrAll (idAll) 8 Форма закрыта нажатием кнопки All mrNoToAll (idNoToAll) 9 Форма закрыта нажатием кнопки NoToAll mrYesToAll (idYesToAll) 10 Форма закрыта нажатием кнопки YesToAll Таким образом, присвоение ModalResult значения от 1 до 10 имитирует нажатие одной из кнопок закрытия окна из стандартного набора Windows. Окно, создавшее модальную форму, может узнать, каким образом было закрыто окно. Для этого необходимо сравнить результат, возвращаемый функцией ShowModal, с константами из таблицы 5.2 (этот метод, очевидно, прерывает работу кода до момента закрытия модального окна): Application->CreateForm(__classid(TForm2), &Form2); int mr=Form2->ShowModal(); if(mr==mrOk) {MessageBox(NULL,"Окно закрыто нажатием кнопки ОК","Внимание",MB_OK); //работа с компонентами формы Form2, измененными пользова //телем при работе с ней в модальном режиме } delete Form2; В коде формы Form2 необходимо в таком случае в тот момент, когда требуется закрыть форму, выполнить присваивание ModalResult=mrOk. Альтернативным вариантом является использование свойства ModalResult кнопок типа TButton или TBitBtn. Задав для этого свойства кнопки на форме одно из значений из таблицы 5.2, программист определит, что при нажатии этой кнопки окно закроется, и статус закрытия будет совпадать со значением свойства ModalResult кнопки. 5.3. Многодокументный интерфейс (MDI) Многие современные приложения поддерживают многооконный режим работы, когда в каждом окне осуществляется работа с отдельным документом. Подобный интерфейс имеет устоявшийся протокол взаимодействия окон, когда одно из окон является главным, а остальные – дочерними. Назначение главного окна – управлять дочерними окнами, меню этого окна обычно
  • 9. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 9 содержит команды создания, удаления дочерних окон, изменения порядка их расположения в клиентской области главного окна. Закрытие родительского окна ведет к завершению работы всего приложения. Дочерние окна предназначены для отображения редактируемого документа. В помощь программисту для реализации подобного интерфейса приложения Windows поддерживает спецификацию MDI (Multiple Document Interface). На уровне операционной системы MDI поддерживается специальным набором API-функций и сообщений. Для программиста на C++Builder MDI интерфейс доступен как набор свойств и методов все того же компонента TForm. Для того, чтобы объявить форму родительской MDI-формой, необходимо присвоить ее свойству FormStyle значение fsMDIForm. Для дочерней формы это свойство необходимо установить в fsMDIChild. Дочернюю форму необходимо отнести к доступным для создания формам (рис. 5.1), поскольку дочерние окна должны создаваться пользователем в процессе работы программы. Тогда код создания дочерней формы должен выглядеть следующим образом: void __fastcall TForm1::new1Click(TObject *Sender) { TForm2 *child=new TForm2(Application); child->Show(); } Для управления созданными дочерними окнами можно использовать несколько свойств и методов. Прежде всего, необходимо обратить внимание на массив MDIChildren, который для главной MDI-формы хранит адреса всех существующих на данный момент дочерних окон. При этом количество дочерних окон можно получить из свойства MDIChildCount. Адрес активной дочерней формы хранится в свойстве ActiveMDIChild. Пример переименования всех дочерних окон приведен в следующем листинге: for(i=0;i<MDIChildCount;i++) MDIChildren[i]->Caption="Window"+IntToStr(i+1); Порядок расположения дочерних окон в клиентской области родительского окна можно изменять вызовами методов Tile и Cascade для главной формы. Метод Tile выстраивает дочерние окна рядом друг с другом, в зависимости от значения свойства TileMode они выстраиваются по горизонтали (tbHorizontal) или по вертикали (tbVertical). Метод Cascade выстраивает дочерние
  • 10. Лекция №11 для дисциплин: «Прикладное программирование» и «Языки программирования» 10 окна каскадом. Для упорядочивания свернутых в пиктограмму дочерних окон в клиентской области родительского окна используется метод ArrangeIcons. Особенностью работы дочерних MDI-окон является то, что при закрытии их методом Close или нажатием кнопки закрытия окна в его заголовке они по умолчанию сворачиваются в пиктограмму, а не закрываются. Закрываться они будут только если в обработчике события OnClose дочернего MDI-окна присваивать параметру Action значения caFree или caHide. Еще одна особенность взаимодействия родительского и дочерних MDI-окон – встраивание меню дочернего окна в состав родительского. Если для дочернего окна спроектировано меню (чаще всего оно включает команды для работы с документом), то оно будет встроено в меню родительского окна (которое обычно содержит команды управления окнами). Порядок следования пунктов меню дочернего окна в родительском меню, а, следовательно, и место встраивания меню дочернего окна определяется значением свойства GroupIndex каждого раздела меню. Именно поэтому, если не изменять значения свойства GroupIndex у меню родительского и дочернего окна, то в процессе работы второе может подменять собой первое, что является очень распространенной ошибкой начинающих программистов. Это происходит потому, что их свойствам GroupIndex по умолчанию присваиваются одинаковые значения, и при появлении дочернего окна его меню встраивается на те же позиции, которые должны занимать пункты родительского меню. Задача программиста – следить, чтобы пункты меню родительского и дочернего окон имели различные значения свойства GroupIndex. Вывод Форма является основным компонентом в проекте приложения на C++Builder, что обусловлено особенной ролью окна в ОС Windows. Формы C++Builder реализуются на основе класса TForm, который позволяет программисту отслеживать основные стадии работы окна: создание, отображение, перерисовка, закрытие, уничтожение, а также управлять окном и его подчиненными элементами. Для форм предусмотрены модальный и немодальный режимы отображения. Окно в модальном режиме фокусирует на себя весь ввод информации в приложение. Если приложение должно работать в многодокументном режиме, то для него можно использовать специальный MDI-интерфейс, который поддерживается классом TForm.