Диалоговые окна существуют модальные(modal dialog box создаются функцией DialogBox)и немодальные (modeless dialog box создаются функцией CreateDialog). Эти две функции загружают шаблон диалогового окна из исполняемого файла прикладной программы и создают выскакивающее окно, которое соответствует спецификации шаблона. Имеются и другие функции, которые создают диалоговое окно, используя шаблоны в памяти; они передают дополнительную информацию в процедуру диалогового окна, как создается диалоговое окно.
Чтобы создать или модальное, или немодальное диалоговое окно, прикладная программа должна снабдить блок диалога шаблоном, чтобы описать стиль и содержание диалогового окна; приложение должно также снабдить диалоговое окно процедурой, чтобы выполнять задачи. Шаблон диалогового окна (dialog box template) - бинарное описание диалогового окна и органов управления, которое оно содержит. Разработчик может создать этот шаблон как ресурс, который будет загружен из исполняемого файла прикладной программы, или создать в памяти, пока прикладная программа выполняется. Процедура диалогового окна (dialog box procedure) - определяемая программой функция повторного вызова, которую система вызывает, когда операционная система получает ввод данных для диалогового окна или задачу для выполнения в блоке диалога. Хотя процедура диалогового окна подобна оконной процедуре, у нее нет тех же самых обязанностей.
Шаблон диалогового окна - это двоичные данные, который описывают диалоговое окно, определяя его высоту, ширину, стиль и органы управления, который он содержит. Чтобы создать диалоговое окно, система или загружает его шаблон из ресурсов в исполняемом файле приложения, или использует шаблон, переданный приложением для неё в глобальной памяти. В любом случае, приложение при создании диалогового окна должно предоставлять шаблон. Разработчик создает ресурсы шаблона, используя компилятор ресурса или редактор диалогового окна. Компилятор ресурса преобразует описание текста в двоичный ресурс, а редактор диалогового окна сохраняет в интерактивном режиме созданное диалоговое окно как двоичный ресурс.
Шаблон устанавливает позицию, ширину, высоту, стиль, идентификаторы и класс окна для каждого органа управления в диалоговом окне. Система создает каждый орган управления путем передачи их данных в функцию CreateWindowEx. Органы управления создаются по порядку, в котором они определены в шаблоне. Шаблон должен определять соответствующее число, тип и порядок органов управления, чтобы гарантировать, что пользователь сможет сделать ввод необходимых данных, чтобы завершить задачу, связанную с диалоговым окном.
Для каждого органа управления шаблон устанавливает значения стиля, которые определяют внешний вид и работу органа управления. Каждый орган управления - это дочернее окно и, поэтому, должно иметь стиль WS_CHILD. Чтобы гарантировать, что орган управления видимый, когда на экране показывается диалоговое окно, каждый орган управления должен иметь также и стиль WS_VISIBLE. Другие, обычно используемые стили окна - это WS_BORDER для органов управления, которые не обязательно имеют рамки, WS_DISABLED для органов управления, которые должны быть блокированы, когда создается первоначальное диалоговое окно и WS_TABSTOP и WS_GROUP для органов управления, к которым можно обращаться, используя клавиатуру. Стили WS_TABSTOP и WS_GROUP используются совместно с клавиатурным интерфейсом диалога, рассмотренным позже в этой главе.
Шаблон может также установить стили, специфические для класса окна органа управления. Например, шаблон, который определяет кнопку управления, должен дать ей стиль, такой как BS_PUSHBUTTON или BS_CHECKBOX. Система передает стили органов управления в оконную процедуру этого элемента через посредство сообщения WM_CREATE, разрешая процедуре приспосабливать внешний вид и работу органа управления.
Система преобразует значения координат позиции, размеры ширины и высоты из базовых единиц измерения диалогового окна в пиксели, перед передачей их в функцию CreateWindowEx. Когда система создает орган управления, она определяет диалоговое окно как родительское окно. Это означает, что система всегда воспринимает координаты позиции органа управления как рабочие координаты, относительно верхнего левого угла рабочей области диалогового окна.
Шаблон определяет класс окна для каждого органа управления. Обычно диалоговое окно содержит органы управления, принадлежащие предопределенным классам окна органов управления, такие как класс окна кнопки и поля редактирования. В этом случае, шаблон определяет класс окна путем присваивания соответствующего предопределенного значения атома класса. Когда диалоговое окно содержит орган управления, принадлежащий классу окна пользовательского органа управления, шаблон дает имя этому зарегистрированному классу окна или значение атома, в настоящее время связанного с этим именем.
Чтобы разрешить пользователю закрыть диалоговое окно, шаблон должен установить, по крайней мере, одну командную кнопку и присвоить ей идентификатор управления IDCANCEL. Чтобы разрешить пользователю выбирать между завершением и отменой задачи связанной с диалоговым окном, шаблон должен установить две командные кнопки. с надписями ОК и Отменить (Cancel), с управляющими идентификаторами IDOK и IDCANCEL, соответственно.
Шаблон устанавливает также и необязательный текст и данные для создания органа управления. Текст обычно предназначен для обозначения кнопок управления или установки начального содержания текста статического органа управления. Данные для создания - это один или несколько байтов данных, которые система передает оконной процедуре органа управления, когда элемент управления создается. Данные для создания полезны для органов управления, которые требуют дополнительной информации о их начальном содержании или стиле, чем это дается другими данными. Например, прикладная программа может использовать данные для создания, чтобы установить начальные параметры и диапазон управления полосой прокрутки.
Процедура диалогового окна похожа на оконную процедуру тем, что система отправляет сообщения процедуре тогда, когда она имеет информацию, чтобы задать или выполнить задачи. В отличие от оконной процедуры, процедура диалогового окна никогда не вызывает функцию DefWindowProc. Вместо этого, она возвращает значение ИСТИНА (TRUE), если обрабатывает это сообщение, или ЛОЖЬ (FALSE), если этого она не делает.
Каждая процедура диалогового окна имеет нижеследующую форму:
BOOL CALLBACK DlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { // Здесь место расположения сообщения. default: return FALSE; } }
Параметры процедуры служат одной и той же цели, что и в оконной процедуре, параметр hwndDlg получает дескриптор окна блока диалога.
Большинство процедур диалогового окна обрабатывает сообщение WM_INITDIALOG и сообщения WM_COMMAND, отправляемые органами управления, но обрабатывает не все, если есть другие сообщения. Если процедура диалогового окна не обрабатывает сообщение, она должна возвратить значение ЛОЖЬ (FALSE), чтобы предписать системе обработать сообщения внутри. Единственным исключением из этого правила является сообщение WM_INITDIALOG. Процедура диалогового окна должна возвратить значение ИСТИНА (TRUE), чтобы предписать системе далее обрабатывать сообщение WM_INITDIALOG. В любом случае, процедура не должна вызвать DefWindowProc.
Модальные диалоговые окна блокируют работу всех остальных окон до тех пока они не будут закрыты. При создании модального диалогового окна, система делает его активным окном. Диалоговое окно остается активным до тех пор, пока процедура диалогового окна не вызовет функцию EndDialog, или система не активизирует окно в другом приложении. Ни пользователь, ни приложение не могут сделать окно владельца активным, пока модальное диалоговое окно не разрушится.
INT_PTR WINAPI DialogBox( __in_opt HINSTANCE hInstance, // указать чтобы вытащить ресурсы из приложения. Если из своего приложения GetModuleHandle(NULL) __in LPCTSTR lpTemplate, // обязательный параметр: шаблон отображения. например если диалогове окно в ресурсе // называется IDD_DIALOG1, тогда параметр запищется так MAKEINTRESOURCE(IDD_DIALOG1) __in_opt HWND hWndParent, // указатель на родителя __in_opt DLGPROC lpDialogFunc // указатель на функцию обработки событий диалогового окна. Функция должна возвращать false );
Пример WinAPI приложения. Нет главного окна. Все приложение построено на диалоговых окнах.
/* WinAPI приложение. Нет главного окна. Все приложение построено на диалоговых окнах. По нажатию правой клавиши мыши появляется дочернее окно. Что бы программа заработала нужно создать файл ресурсов диалоговыми окнами: IDD_DIALOG1 и IDD_DIALOG2 */ #include <windows.h> #include <tchar.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // прототип функции WndProc INT_PTR CALLBACK DialogProc(HWND , UINT , WPARAM ,LPARAM );// прототип функции диалогового окна INT_PTR CALLBACK DialogProc1(HWND , UINT , WPARAM ,LPARAM ); int WINAPI _tWinMain(HINSTANCE hInstance, // дескриптор текущего экземпляра окна HINSTANCE hPrevInstance, // дескриптор предыдущего экземпляра окна LPTSTR lpCmdLine, // указатель на командную строку int nCmdShow // показывает состояние окна ) { //здесь вызываем диалогове окно, которое и будет главным окном нашей программы. DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_DIALOG1),NULL,DialogProc); return 0; } INT_PTR CALLBACK DialogProc(HWND hWnddialog, UINT uMsg, WPARAM ,LPARAM )// прототип функции диалогового окна { switch (uMsg) { case WM_RBUTTONDOWN: //DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_DIALOG2),hWnddialog,DialogProc1); break; case WM_CREATE: { }break; case WM_CLOSE: EndDialog(hWnddialog,0); break; default: return false; } //return false; } INT_PTR CALLBACK DialogProc1(HWND hWnddialog, UINT uMsg, WPARAM ,LPARAM )// прототип функции диалогового окна { switch (uMsg) { case WM_CLOSE: EndDialog(hWnddialog,0); break; default: return false; } }
// Глобальные переменные: HWND hwndInfo = NULL; // дескриптор немодального окна. Проверять, чтобы не запустить два одинаковых окна. ... case WM_COMMAND:{ if (LOWORD(wParam) == IDOK) { if (!IsWindow(hwndInfo)) { hwndInfo = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_INFO), hWnddialog, InfoProc); ShowWindow(hwndInfo, SW_SHOW); } return (INT_PTR)TRUE; } } break;