![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Использование немодального диалога
Рис. 5.3. Пример работы Win-приложения с окном ввода
В завершение данной главы преобразуем модальный диалог из предыдущего примера в немодальный. Использование немодального диалога потребует несколько больше усилий, чем использование модального, — в основном потому, что немодальный диалог является более независимым окном, нежели модальный. В процессе работы немодального диалога программа остается активной, так что диалог и породившее его окно продолжают получать сообщения. Таким образом, для включения в программу немодального диалога необходимо вставить дополнительный фрагмент в цикл обработки сообщений Вашей программы. Для создания немодального диалога вместо функции DialogBox() используется функция API CreateDialog(): HWND CreateDialog(HINSTANCE hThisInst, LPCSTR lpName, HWND hwnd, DLGPROC IpDFunc);
Здесь hThisInst – дескриптор текущего экземпляра приложения, который передается в качестве параметра в функцию WinMain(), lpName – имя диалога, определенное в файле ресурсов, hwnd — дескриптор родительского окна для диалога, а lpDFunc – указатель на функцию диалога. Функция диалога в данном случае должна быть описана так же, как и для модального диалога. В отличие от модального немодальный диалог не отображается на экране после создания, и чтобы получить такое изображение, Вам может понадобиться вызов функции ShowWindow(). Однако если при определении диалога в файле ресурсов добавить стиль WS_VISIBLE, диалог будет отображаться автоматически. Для завершения немодального диалога программа должна вызвать функцию DestroyWindow(), а не EndDialog(). Прототип функции DestroyWindow() имеет следующий вид: BOLL DestroyWindow(HWND hwnd); Параметр hwnd должен задавать дескриптор закрываемого окна (в данном случае диалога). Поскольку главное окно Вашего приложения будет продолжать получать сообщения, когда немодальный диалог будет активным, необходимо внести изменения в цикл обработки сообщений. Для этого следует добавить вызов функции IsDialogMessage(), направляющей сообщения диалога Вашему немодальному диалогу: BOOL IsDialogMessage(HWND hdwnd, LPMSG msg); Здесь hdwnd содержит дескриптор окна немодального диалога, a msg – сообщение, полученное в функции GetMessage(). Эта функция возвращает ненулевое значение, если сообщение предназначено для диалога, и нуль в противном случае. Если сообщение предназначено для диалога, оно будет автоматически направлено ему. Таким образом, для работы с немодальным диалогом цикл обработки сообщений Вашей программы должен выглядеть следующим образом:
while(GetMessage(& msg, NULL, 0, 0)) if(! IsDialogMessage(hDlg, & msg)) if(! TranslateAccelerator(hwnd, hAccel, & msg)) { TranslateMessage(& msg); // использ.клавиатуры DispatchMessage (& msg); // возврат к Windows }
Как видите, сообщение обрабатывается обычным образом только в том случае, если оно не предназначено для диалога. Создание немодального диалога. Преобразование модального диалога из предыдущего примера в немодальный потребует небольших изменений в программе. Прежде всего необходимо внести изменения в файл ресурсов Mydialog.rc. Поскольку немодальный диалог при создании не отображается автоматически, добавьте в определение диалога стиль WS_VISIBLE. Так как с момента создания файла Mydialog.rc мы внесли в него довольно много изменений, для удобства приведем этот файл целиком:
// Пример файла ресурсов, описывающего меню и диалог #include " Mydialog.h" #include < Windows.h> MYMENU MENU { MENUITEM " Диалог & 1", IDM_DIALOG1 MENUITEM " Диалог & 2", IDM_DIALOG2 MENUITEM " Помощь", IDM_HELP } MYMENU ACCELERATORS { VK_F2, IDM_DIALOG1, VIRTKEY VK_F3, IDM_DIALOG2, VIRTKEY VK_F1, IDM_HELP, VIRTKEY } MYDB DIALOG 18, 18, 142, 92 CAPTION " Первый диалог" STYLE DS_MODALFRAME|WS_POPUP|WS_CAPTION|WS_SYSMENU| WS_VISIBLE { DEFPUSHBUTTON " Красный", IDD_RED, 57, 45, 36, 14, WS_CHILD|WS_VISIBLE|WS_TABSTOP PUSHBUTTON " Зеленый", IDD_GREEN, 95, 45, 36, 14, WS_CHILD|WS_VISIBLE|WS_TABSTOP PUSHBUTTON " Сброс", IDCANCEL, 52, 65, 37, 14, WS_CHILD|WS_VISIBLE|WS_TABSTOP PUSHBUTTON " Выбери фрукт", IDD_SELFRUIT, 2, 45, 50, 14, WS_CHILD| WS_VISIBLE|WS_TABSTOP LISTBOX ID_LB1, 2, 10, 47, 28, LBS_NOTIFY|WS_CHILD| WS_VISIBLE| WS_BORDER|WS_VSCROLL| WS_TABSTOP EDITTEXT ID_EB1, 68, 8, 72, 12, ES_LEFT| ES_AUTOHSCROLL|WS_CHILD|WS_VISIBLE| WS_BORDER|WS_TABSTOP PUSHBUTTON " Конец ввода", IDOK, 68, 22, 60, 14, WS_CHILD|WS_VISIBLE|WS_TABSTOP }
Далее в программу необходимо внести следующие изменения: 1) вызвать IsDialogMessage() в цикле обработки сообщений. 2) создать диалог, используя функцию CreateDialog(), а не функцию DialogBox(). 3) для закрытия диалога заменить функцией DestroyWindows() функцию EndDialog().
Пример 5-4. Полный текст программы, использующей немодальный диалог (с внесенными изменениями), приводится ниже. Пример работы программы приведен на рис. 5.4. Обязательно попробуйте запустить эту программу, чтобы полностью понять разницу между модальным и немодальным диалогами. Рис. 5.4. В немодальном режиме основная программа и диалог работают параллельно
// Демонстрация немодального диалога #include < Windows.h> #include < String.h> #include < Stdio.h> #include " Mydialog.h"
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK DialogFunc(HWND, UINT, WPARAM, LPARAM); char szWinName[]=" МоеОкно"; // Имя класса окна HINSTANCE hInst; HWND hDlg; // Дескриптор окна диалога int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) { HWND hwnd; MSG msg; WNDCLASS wcl; HACCEL hAccel; // Определить класс окна wcl.hInstance=hThisInst; // Дескриптор приложения wcl.lpszClassName=szWinName; // Имя класса окна wcl.lpfnWndProc=WindowFunc; // функция окна wcl.style=0; // Стиль по умолчанию wcl.hIcon=LoadIcon(NULL, IDI_APPLICATION); // Иконка wcl.hCursor=LoadCursor(NULL, IDC_ARROW); // Курсор wcl.lpszMenuName=" MYMENU"; // Меню wcl.cbClsExtra=0; // Без дополнит. информации wcl.cbWndExtra=0; wcl.hbrBackground // Заполнение окна белым цветом =(HBRUSH)GetStockObject(WHITE_BRUSH); if(! RegisterClass(& wcl)) return 0; // Зарегистрировать класс окна // Создать окно: hwnd=CreateWindow(szWinName, // Имя класса " Вызов немодального диалога", // Загол. WS_OVERLAPPEDWINDOW, // Стиль окна CW_USEDEFAULT, // Х-координата CW_USEDEFAULT, // Y-координата CW_USEDEFAULT, // Ширина по умолчанию CW_USEDEFAULT, // Высота по умолчанию HWND_DESKTOP, // Нет родительского окна NULL, // Нет меню hThisInst, // Дескриптор приложения NULL); // Без дополнительных аргументов hInst=hThisInst; // Сохранить дескриптор текущего // Загрузить акселераторы: hAccel=LoadAccelerators(hThisInst, " MYMENU"); // Показать окно и перерисовать содержимое: ShowWindow(hwnd, nWinMode); UpdateWindow(hwnd); // Запустить цикл обработки сообщений: while(GetMessage(& msg, NULL, 0, 0)) if(! IsDialogMessage(hDlg, & msg)) if(! TranslateAccelerator(hwnd, hAccel, & msg)) { TranslateMessage(& msg); // Исп. клавиатуру DispatchMessage (& msg); //Возврат к Windows } return msg.wParam; }
// Следующая функция вызывается ОС Windows и получает // в качестве параметров сообщения из очереди // сообщений данного приложения
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_COMMAND: switch(LOWORD(wParam)) { case IDM_DIALOG1: hDlg=CreateDialog(hInst, " MYDB", hwnd, DialogFunc); break; case IDM_DIALOG2: MessageBox(hwnd, " Работает параллельно с первым", " Второй диалог", MB_OK); break; case IDM_HELP: MessageBox(hwnd, " Помощь", " Помощь", MB_OK); break; } break; case WM_DESTROY: /* завершение программы */ PostQuitMessage(0); break; default: // Все сообщения, не обрабатываемые // в данной функции, направляются // на обработку по умолчанию return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }
// Простая функция диалога BOOL CALLBACK DialogFunc(HWND hdwnd, UINT message, WPARAM wParam, LPARAM lParam) { long i; char str[80]; switch(message) { case WM_COMMAND: switch(LOWORD(wParam)) { case IDCANCEL: DestroyWindow(hdwnd); return 1; case IDD_RED: MessageBox(hdwnd, " Выбран Красный", " Красный", MB_OK); return 1; case IDD_GREEN: MessageBox(hdwnd, " Выбран Зеленый", " Зеленый", MB_OK); return 1; case ID_LB1: // Сообщение от списка, если // это, конечно, LBN_DBLCLK if(HIWORD(wParam) == LBN_DBLCLK) { // Получ. индекс выбран. элемента i=SendDlgItemMessage(hdwnd, ID_LB1, LB_GETCURSEL, 0, 0L); sprintf (str, " Индекс выбранного элемента %d", i); MessageBox(hdwnd, str, " Сделан выбор", MB_OK); } return 1; case IDD_SELFRUIT: //Кнопка " Выбери фрукт" i=SendDlgItemMessage(hdwnd, ID_LB1, LB_GETCURSEL, 0, 0L); if(i > -1) sprintf (str, " Индекс выбранного элемента %d", i); else sprintf(str, " Фрукт не выбран"); MessageBox(hdwnd, str, " Сделан выбор", MB_OK); return 1; case IDOK: // Кнопка IDOK " Конец ввода" GetDlgItemText(hdwnd, ID_EB1, str, 80); MessageBox(hdwnd, str, " Содержимое окна ввода", MB_OK); return 1; } case WM_INITDIALOG: // Инициализация списка SendDlgItemMessage(hdwnd, ID_LB1, LB_ADDSTRING, 0, (LPARAM)" Яблоко"); SendDlgItemMessage(hdwnd, ID_LB1, LB_ADDSTRING, 0, (LPARAM)" Апельсин"); SendDlgItemMessage(hdwnd, ID_LB1, LB_ADDSTRING, 0, (LPARAM)" Груша"); SendDlgItemMessage(hdwnd, ID_LB1, LB_ADDSTRING, 0, (LPARAM)" Виноград"); return 1; } return 0; }
В данной главе лишь поверхностно описаны те операции, которые можно выполнять с диалогом и различными элементами управления. Другие элементы управления рассматриваются далее. Вы можете самостоятельно поэкспериментировать, изучая свойства элементов управления.
|