Учебное пособие: Подклассы окон
HWND CreateDialogIndirect( hInstance, hglbDlgTemplate, hWndOwner, lpfnDlgProc );
HWND CreateDialogIndirectParam(
hInstance, hglbDlgTemplate, hWndOwner, lpfnDlgProc, lParamInit
);
Для создания диалога необходимо передать соответствующей функции структуру данных, описывающую этот диалог (то есть указывающую стили, размеры, положение и идентификаторы управляющих элементов и самого диалога).
Половина из перечисленных функций, содержащих слово ...Indirect... в названии, использует хендл глобального блока памяти hglbDlgTemplate в котором должна размещаться такая структура. Вы должны сами позаботиться о создании и заполнении этого блока данными.
Другая половина функций, не содержащих слова ...Indirect... в названии, использует имя (номер) ресурса, описывающего эту структуру данных. При этом приложение должно содержать ресурс типа DIALOG, для которого компилатор ресурсов создает нужный блок данных. Вы можете сами загружать ресурс в блок глобальной памяти, что-либо корректировать в нем, если это необходимо, и использовать функцию ...Indirect... для создания диалога.
Кроме информации о самом диалоге Вы должны указать хендл копии приложения, с которой будет связано окно диалога, и которое содержит требуемые ресурсы; хендл окна - пользователя диалога (о различии Owner и Parent мы уже говорили). Помимо этого Вы должны указать адрес процедуры, обрабатывающей сообщения диалога lpfnDlgProc (об этой функции чуть позже). Это должен быть адрес функции, связанной с копией приложения с помощью функции MakeProcInstance.
Когда окно диалога создается, оно дополнительно получит сообщение WM_INITDAILOG, которое используется для инициализации управляющих элементов. Вы можете передать вместе с этим сообщением параметр lParam, содержащий нужные Вам данные. Для этого предназначены функции, содержащие слово ...Param в названии.
Модальные и немодальные диалоги
Диалоги разделяются на два общих класса - модальные (modal) и немодальные (modeless) диалоги. Модальные диалоги требуют обязательного завершения для продолжения работы всего приложения. Пример – диалог для выбора файла в редакторе. До тех пор, пока файл не выбран продолжение работы редактора бессмыслено.
Немодальные диалоги работают паралелльно с остальным приложением. Пример – диалог поиск/замена в большинстве редакторов. Вы можете перейти в окно редактора и поработать там, не завершая работу с диалогом. При этом Вы можете оперировать как с диалогом, так и с остальными окнами Вашего приложения.
Разница между модальными и немодальными диалогами на программном уровне заключается в правилах обработки сообщений, поступающих к этим диалогам.
Модальный диалог, работающий монопольно, должен исключить передачу сообщений к остальным окнам приложения. Для этого организуется новый цикл обработки сообщений, обрабатывающий все сообщения, нужные диалогу, и исключающие обработку сообщений, направленных другим окнам приложения (исключаются, в основном, сообщения от клавиатуры и мыши).
Для создания модальных диалогов предназначены функции DialogBox..., которые создают требуемый диалог и организуют цикл обработки сообщений для этого диалога.
При этом надо быть достаточно аккуратным - Ваш главный цикл обработки сообщений будет бездействовать, и какая-либо дополнительная обработка сообщений в нем будет игнорирована. Так, например, акселераторы, транслируемые в главном цикле обработки сообщений, не окажут никакого эффекта в модальном диалоге.
Немодальный диалог, работающий параллельно с остальным приложением, получает сообщения через главный цикл обработки сообщений. То есть окно диалога, вместе со всеми управляющими элементами, выступает в качестве самого обычного окна приложения.
Для создания немодального диалога Вам надо создать окно диалога с помощью функции CreateDialog..., и предусмотреть специальную обработку сообщений для диалога в главном цикле обработки сообщений. Модификация главного цикла обработки сообщений производится следующим образом:
MSG msg;
HWND hWndModeless= NULL;
...
while ( GetMessage( &msg, NULL, NULL, NULL ) ) {
if ( !hWndModeless || !IsDialogMessage( hWndModeless, &msg ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
ПорядокпримененияфункцийIsDialogMessageиTranslateAcceleratorопределяетсяжелаемымэффектом: еслиВамнадо, чтобыакселераторыиспользовалисьдиалогом, тотрансляциюакселераторанадопроизводитьдовызовафункцииIsDialogMessage. Обычно это не требуется и трансляция производится позже.
В некоторых случаях Вы можете с помощью CreateDialog иммитировать модальный диалог, организовав после создания окна дилога дополнительный цикл обработки сообщений. При этом Вы можете предусмотреть специальную трансляцию некоторых сообщений.