Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторный практикум «Основы разработки приложений Windows» книга 1.DOC
Скачиваний:
107
Добавлен:
10.05.2014
Размер:
721.41 Кб
Скачать

Обслуживание модального диалога

Открытие модального диалога осуществляется в нашем примере (да и практически всегда) при выборе соответствующей команды меню (у нас – команды "Открыть..."с идентификаторомMI­ABOUT). Как уже отмечалось ранее, выбор любого пункта меню заставляет Windows послать в приложение сообщениеWMCOM­MAND, что приводит к передаче управления на прикладную фун­кциюOnCommand().Через второй параметр этой функции передается значение идентификатора выбранного пункта меню. Анализ идентификатора с помощью конструкцииswitch-case позволяет выполнить в ответ на выбор каждого пункта меню тре­буемые действия. Открытие модального диалога осуществляется вызовом функции WindowsDialogBox().

Как можно увидеть из примера 4-1, функция DialogBox()использует четыре параметра. Первый из них – дескриптор приложения. Этот дескриптор не передается автоматически в оконную функцию и далее в функции обработки сообщений. Имея в виду, что он понадобится нам для вызова функцииDialogBox(), мы сохранили его в глобальной переменнойhInеще в процессе регистрации главного окна приложения.

Вторым аргументом функции DialogBox()служит указатель на имя диалога, использованное в сценарии этого диалога в файле ресурсов (или само это имя). У нас это строка"About".

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

Четвертый аргумент принципиально является важнейшим; он представляет собой имя оконной функции для окна диалога. Как уже отмечалось, каждое окно, входящее в состав приложения, обязано иметь свою оконную функцию. Оконная функция диалога вызывается системой Windows в процессе инициализации диалога, а также при выполнении пользователем каких-либо операций с элементами управления диалогового окна. Параметры этой функции такие же, как у оконной функции главного окна, однако возвращаемое значение должно иметь тип не LRESULT, аBOOL. Роль функции создания диалогаDialogBox() заключается прежде всего в том, что она привязывает к окну диалога соответствующую ему оконную функцию, состоящую из фрагментов обслуживания элементов управления диалогового окна.

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

Для большей части сообщений, поступающих в диалоговое окно, в файле WINDOWSX.Hможно найти макросы видаHANDLE­WMсообщение, поэтому структура оконной функции диалога может быть в точности такой же, как и для оконной функции главного окна:

BOOL CALLBACK DlgProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){

switch(msg){

HANDLE_MSG(hwnd,WM_INITDIALOG,DlgOnInitDialog);

HANDLE_MSG(hwnd,WM_COMMAND,DlgOnCommand);

default:

return FALSE;//Возврат FALSE для остальных сообщений

}

}

На первый взгляд такое решение представляется не вполне корректным. Действительно, оконная функция обычного (не диалогового) окна в соответствии с ее прототипом должна возвращать значение типа LRESULT, и макросыHANDLEWMсообщениедолжны приводить к возврату именно такого значения, в то время как макросы, используемые в оконной функции диалога, должны возвращать, в соответствии сеепрототипом, значение типаBOOL.Однако в 32-разрядных приложениях оба эти типа: иBOOL, и LRESULT –представляют собой попросту целые числа (как, между прочим, иHWND, WPARAM, LPARAM,HPEN и др.), и их можно свободно преобразовывать друг в друга по правилам явного преобразования языка С++. В макроопределениях макросовHANDLEWM­сообщение, выполняются в необходимых случаях такие преобразования (часто сразу в несколько типов, например,LRESULT, DWORD, UINT и дажеHBRUSH), что дает возможность использовать эти макросы как в обычных, так и в диалоговых оконных функциях.

Рассмотрим отличия диалоговой функции. Для диалогов нет необходимости, более того, недопустимо вызывать функцию обработки сообщений по умолчанию DefWindowProc(). Эта функция вызывается только для окон (главного и порожденных), которые строит и обслуживает пользователь. Диалог же организует и поддерживает Windows, которая и так знает, что ей надлежит делать с большинством сообщений, поступающих в диалоговое окно.

Надо заметить, что в процессе создания диалога и работы с ним Windows посылает в него большое количество сообщений, на которые сама же и отвечает. Программа же обрабатывает лишь немногие из них. Прежде всего, это сообщение WMINITDIALOG о создании диалога и WMCOMMAND о работе пользователя с элементами управления; во многих случаях приходится обрабатывать и другие сообщения.

Windows должна знать, какие сообщения мы обрабатываем, а какие нет. Обычно руководствуются следующим правилом: если оконная функция диалога обрабатывает сообщение, она возвращает значение TRUE, а если не обрабатывает –FALSE. Поэтому для всех сообщений, не обрабатываемых в приложении, надо просто завершить оконную функцию, вернув значениеFALSE(см. предложение сdefaultв приведенном выше фрагменте).

В рассматриваемом примере обрабатываются лишь два сообщения модального диалога. Сообщение WMINITDIALOGпоступает в диалоговое окно непосредственно перед его выводом на экран и предназначено для выполнения инициализирующих действий, если они предусмотрены. В нашей программе их нет, однако перехват сообщенияWMINITDIALOGвсе же имеет смысл. Дело в том, что возврат в Windows в ответ на это сообщение значенияTRUEприводит к специфическим действиям – установке так называемого фокуса ввода на определенный элемент управления диалогом. Обычно это элемент, описанный первым в файле ресурсов. Если элемент управления владеет фокусом ввода, то в него поступают все сообщения от клавиатуры. Если фокус ввода установлен, например, на поле для ввода текста, то вводимый с клавиатуры текст будет попадать именно в это поле; если фокус ввода установлен на кнопке, нажатие клавиши Enter приведет к “нажатию” этой кнопки. В нашем диалоге предусмотрена единственная кнопка"Закрыть", и помещение на нее фокуса ввода позволяет управлять этой кнопкой не только мышью, но и клавишей Enter. Между прочим, имея в виду такую возможность, мы поместили предложение описания кнопкипервымв перечне элементов управления (которых у нас всего два).

Второе обрабатываемое в программе сообщение, WMCOMMAND, поступает в диалоговое окно в следующих случаях:

  • нажата кнопка "Закрыть"; передаваемый в функцию обработки сообщенияWMCOMMANDидентификатор элемента управленияidравен в нашем случаеID_OK(id=100), поскольку именно эта константа закреплена за кнопкой в файле ресурсов;

  • с клавиатуры введена команда Alt+F4 (id=IDCANCEL=2);

  • пользователь щелкнул по кнопке в правом верхнем углу диалогового окна (id=IDCANCEL).

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

Функция EndDialog()вызывает два действия: гасится диалоговое окно и завершается выполнение функцииDialogBox(). Вспомним, что для вывода на экран модального диалога надо вызывать функциюDialogBox(). Вспомним также, что пока на экране присутствует окно модального диалога, все остальные окна приложения блокированы: пользователь может работать только с элементами управления модального диалога. Именно этим модальный диалог и отличается от немодального, который не препятствует манипуляциям с любыми другими окнами и элементами управления приложения.

Все время, пока пользователь работает с модальным диалогом, выполняется функция DialogBox(). Другими словами, выполнение программы как бы остановилось в точке вызова DialogBox() в функции OnCommand(), которая является фрагментом оконной функции главного окна. Эта остановка не мешает Windows вызывать по мере необходимости оконную функцию диалога и вложенные в нее подпрограммы; однако пока программа не завершила обработку сообщения WM_COMMAND главного окна, она не может перейти к обработке следующих сообщений, поступающих в главное окно.

Вызов функции EndDialog()завершает выполнение функцийDialogBox()и (в нашем случае)OnCommand(), снова активизируя главное окно приложения.

Функция EndDialog() требует двух параметров типов HWND и int соответственно. Первый – это, естественно, дескриптор диалогового окна, передаваемый из Windows в оконную функцию диалога DlgProc() при ее вызове, а из нее в функцию DlgOnCommand(). Второй параметр представляет собой целое число, которое будет служить возвращаемым значением для функции создания диалогового окна DialogBox(). Для того, чтобы использовать это значение, открывать диалог следовало так:

int result=DialogBox(...);

Тогда второй фактический аргумент функции EndDialog()вернулся бы в переменнуюresult. Таким образом создается возможность обрабатывать коды завершения диалогового окна.