Присвоение параметру Action значения caMinimize приводит к сворачиванию окна в пиктограмму. Это значение присваивается по умолчанию для дочерних MDI-окон.
Если же параметру Action присвоить значение caFree, то будет разрешено удаление формы. После этого процесс удаления формы становится необратимым, для формы сработает еще одно событие OnDestroy. В момент возникновения этого события окно уже невидимо на экране, отменить его уничтожение невозможно, основное назначение обработчика события 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 либо кнопкой закрытия в заголовке окна |
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)
Многие современные приложения поддерживают многооконный режим работы, когда в каждом окне осуществляется работа с отдельным документом. Подобный интерфейс имеет устоявшийся протокол взаимодействия окон, когда одно из окон является главным, а остальные – дочерними. Назначение главного окна – управлять дочерними окнами, меню этого окна обычно содержит команды создания, удаления дочерних окон, изменения порядка их расположения в клиентской области главного окна. Закрытие родительского окна ведет к завершению работы всего приложения. Дочерние окна предназначены для отображения редактируемого документа. В помощь программисту для реализации подобного интерфейса приложения 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 выстраивает дочерние окна каскадом. Для упорядочивания свернутых в пиктограмму дочерних окон в клиентской области родительского окна используется метод ArrangeIcons.
Особенностью работы дочерних MDI-окон является то, что при закрытии их методом Close или нажатием кнопки закрытия окна в его заголовке они по умолчанию сворачиваются в пиктограмму, а не закрываются. Закрываться они будут только если в обработчике события OnClose дочернего MDI-окна присваивать параметру Action значения caFree или caHide.
Еще одна особенность взаимодействия родительского и дочерних MDI-окон – встраивание меню дочернего окна в состав родительского. Если для дочернего окна спроектировано меню (чаще всего оно включает команды для работы с документом), то оно будет встроено в меню родительского окна (которое обычно содержит команды управления окнами). Порядок следования пунктов меню дочернего окна в родительском меню, а, следовательно, и место встраивания меню дочернего окна определяется значением свойства GroupIndex каждого раздела меню. Именно поэтому, если не изменять значения свойства GroupIndex у меню родительского и дочернего окна, то в процессе работы второе может подменять собой первое, что является очень распространенной ошибкой начинающих программистов. Это происходит потому, что их свойствам GroupIndex по умолчанию присваиваются одинаковые значения, и при появлении дочернего окна его меню встраивается на те же позиции, которые должны занимать пункты родительского меню. Задача программиста – следить, чтобы пункты меню родительского и дочернего окон имели различные значения свойства GroupIndex.
Вывод
Форма является основным компонентом в проекте приложения на C++Builder, что обусловлено особенной ролью окна в ОС Windows. Формы C++Builder реализуются на основе класса TForm, который позволяет программисту отслеживать основные стадии работы окна: создание, отображение, перерисовка, закрытие, уничтожение, а также управлять окном и его подчиненными элементами. Для форм предусмотрены модальный и немодальный режимы отображения. Окно в модальном режиме фокусирует на себя весь ввод информации в приложение. Если приложение должно работать в многодокументном режиме, то для него можно использовать специальный MDI-интерфейс, который поддерживается классом TForm.
6. Работа с клавиатурой и мышью в среде C++Builder
Любое интерактивное приложение должно реагировать на события от клавиатуры и мыши. Рассмотрим, каким образом можно работать с клавиатурой и мышью в приложениях, разработанных в среде C++Builder. Для начала рассмотрим общую схему аппаратного ввода, реализованную в операционных системах семейства Windows. Все аппаратные события, связанные с клавиатурой и мышью, обрабатываются драйверами соответствующих устройств и попадают в системную очередь аппаратного ввода (system hardware input queue, SHIQ). При запуске системы создается особый поток необработанного ввода (raw input thread, RIT), который извлекает очередной элемент из очереди SHIQ и на его основе формирует соответствующие сообщения Windows. Это сообщения: WM_KEYDOWN – нажата клавиша на клавиатуре, WM_KEYUP – отпущена клавиша на клавиатуре, MW_MOUSEMOVE – курсор мыши был перемещен, WM_?BUTTONDOWN – нажата кнопка мыши, WM_?BUTTONUP – отпущена кнопка мыши, WM_?BUTTONDBLCLK – двойное нажатие кнопки мыши (вместо ‘?’ могут быть буквы L, R и M отвечающие, соответственно, за левую, правую и среднюю кнопку мыши). Эти сообщения направляются в очереди виртуального ввода (virtualized input queue, VIQ) нужного потока [3]. Далее они извлекаются в цикле обработки сообщений приложения и поступают на обработку в соответствующую функцию окна. В упрощенном виде необходимый поток выбирается следующим образом: для событий мыши – это поток, создавший окно, над которым находится курсор мыши; для клавиатуры – поток, создавший окно, с которым пользователь работает в данное время.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |


