6.30.3 - Создание немодального диалогового окна

Вы создаете немодальный блок диалога, используя функцию CreateDialog, определяя идентификатор или имя ресурса шаблона и адрес процедуры диалогового окна. CreateDialog загружает шаблон, создает диалоговое окно, но необязательно показывает его. Ваша прикладная программа ответственна за извлечение и диспетчеризацию сообщений о вводе пользователя в процедуре диалогового окна.

В следующем примере прикладная программа отображает немодальное диалоговое окно, если оно еще не отображено, когда пользователь выбирает команду Перейти к (Go To) из меню прикладной программы. Диалоговое окно содержит поле редактирования, окошко для отметки "галочкой" и кнопки OK и CANCEL. Шаблон блока диалога - ресурс в исполняемом файле прикладной программы и имеет идентификатор ресурса DLG_GOTO. Пользователь вводит номер строки в поле редактирования и проставляет в окошке для отметки "галочку", чтобы определить, что номер строки - относится к текущей строке. Идентификаторы элементов управления - ID_LINE, ID_ABSREL, IDOK и IDCANCEL.

Операторы в первой части примера создают немодальное диалоговое окно. Эти операторы, в оконной процедуре для главного окна прикладной программы, создают блок диалога, когда оконная процедура принимает сообщение WM_COMMAND, имеющее идентификатор команды IDM_GOTO, но только тогда, если глобальная переменная hwndGoto еще не содержит правильного дескриптора. Вторая часть примера - главный цикл сообщения прикладной программы. Цикл включает в себя функцию IsDialogMessage, чтобы гарантировать, что пользователь может использовать интерфейс клавиатуры блока диалога в этом немодальном диалоговом окне. Третья часть примера - процедура диалогового окна. Процедура извлекает информацию о содержимом поля редактирования и окошка для отметки "галочкой", когда пользователь выбирает кнопку OK. Процедура уничтожает диалоговое окно, когда пользователь выбирает кнопку Отменить (Cancel).

HWND hwndGoto = NULL;  // дескриптор окна блока диалога 

	. 
	. 
	. 
 
	case WM_COMMAND: 
	switch (LOWORD(wParam)) 
	{ 
		case IDM_GOTO: 
			if (!IsWindow(hwndGoto)) { 
				hwndGoto = CreateDialog(hinst, 
				MAKEINTRESOURCE(DLG_GOTO), 
				hwnd, (DLGPROC) GoToProc); 
				ShowWindow(hwndGoto, SW_SHOW); 
			} 
			break; 
	} 
	return 0L; 

В предшествующих операторах, CreateDialog вызывается только тогда, если hwndGoto, не содержит правильный дескриптор окна. Это гарантирует, что прикладная программа одновременно не отобразит два диалоговых окна. Чтобы поддержать этот метод проверки, процедура блока диалога должна установить hwndGoto в значение ПУСТО (NULL), когда она уничтожает диалоговое окно.

Цикл сообщений для прикладной программы состоит из следующих операторов:

while (GetMessage(&msg, NULL, NULL, NULL)) 
{  
	if (!IsWindow(hwndGoto) || !IsDialogMessage(hwndGoto, &msg)) 
	{ 
		TranslateMessage(&msg); 
		DispatchMessage(&msg); 
	} 
} 

Цикл проверяет правильность дескриптора окна для блока диалога и только тогда вызывает функцию IsDialogMessage, если дескриптор правилен. Функция IsDialogMessage только тогда обрабатывает сообщение, если оно принадлежит диалоговому окну. Иначе, функция возвращает значение ЛОЖЬ(FALSE), а цикл посылает сообщение в соответствующее окно.

Следующие операторы определяют процедуру диалогового окна:

int iLine;		// принимает номер строки  
BOOL fRelative;	// принимает состояние окошка для отметки "галочкой" 

	. 
	. 
	. 

BOOL CALLBACK GoToProc(hwndDlg, message, wParam, lParam) 
HWND hwndDlg; 
UINT message; 
WPARAM wParam; 
LPARAM lParam; 
{ 
	BOOL fError; 
 
	switch (message) { 
		case WM_INITDIALOG: 
			CheckDlgButton(hwndDlg, ID_ABSREL, fRelative); 
			return TRUE; 

		case WM_COMMAND: 
		switch (LOWORD(wParam)) 
		{ 
			case IDOK: 
				fRelative = IsDlgButtonChecked(hwndDlg, 
					ID_ABSREL); 
				iLine = GetDlgItemInt(hwndDlg, ID_LINE, 
					&fError, fRelative); 
				if (fError) { 
					MessageBox(hwndDlg, SZINVALIDNUMBER, 
						SZGOTOERR, MB_OK); 
					SendDlgItemMessage(hwndDlg, ID_LINE, 
						EM_SETSEL, 0, -1L); 
				} else 
					. 
					. // Уведомляет окно владельца, что команда выполнена.
					. 
				return TRUE; 
 
			case IDCANCEL: 
				DestroyWindow(hwndDlg); 
				hwndGoto = NULL; 
				return TRUE; 
		} 
	} 
	return FALSE; 
} 

В предшествующих операторах процедура обрабатывает сообщения WM_COMMAND и WM_INITDIALOG. В ходе обработки WM_INITDIALOG, процедура инициализирует окошко для отметки "галочкой", передавая текущее значение глобальной переменной fRelative в CheckDlgButton. Затем процедура возвращает значение ИСТИНА (TRUE), чтобы заставить Windows установить фокус ввода данных по умолчанию.

В ходе обработки WM_COMMAND, процедура закрывает диалоговое окно только тогда, если пользователь выбирает кнопку Отменить (Cancel) - то есть кнопку, имеющую идентификатор IDCANCEL. Процедура должна вызвать DestroyWindow, чтобы закрыть немодальное диалоговое окно. Обратите внимание, что процедура также устанавливает переменную hwndGoto в значение ПУСТО (NULL), чтобы гарантировать, что другие операторы, которые зависят от этой переменной, действуют правильно.

Если пользователь выбирает кнопку OK, процедура извлекает информацию о текущем состоянии окошка для отметки "галочкой" и присваивает ее переменной fRelative. Затем она использует эту переменную, чтобы извлечь данные о числе строк в поле редактирования. Функция GetDlgItemInt переводит текст в поле редактирования в целое число. Значение fRelative определяет, правильно ли понимает функция число как знаковое или беззнаковое значение. Если текст поля редактирования - не правильное число, GetDlgItemInt устанавливает в переменной fError значение отличное от нуля. Процедура проверяет это значение, чтобы определить, или показать сообщение об ошибке или завершить команду. В случае ошибки, процедура диалогового окна передает сообщение полю редактирования, предписывая ему выбрать текст в элементе управления так, чтобы пользователь мог его легко заменять. Если GetDlgItemInt не возвращает ошибку, процедура может или завершить затребованную команду самостоятельно или передать сообщение окну владельцу, предписывая ему завершить команду.


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Владимир Соковиков - 09.05.2002