На этом шаге мы рассмотрим создание и использование простого диалогового окна.
После создания ваших диалоговых окон с помощью Resource Workshop, файл описания диалогового окна готов к компиляции и вставке в вашу программу. Однако, просто скомпилировать программу с ее файлом ресурсов не достаточно для запуска вашего окна диалога. Для появления диалогового окна в нужное время вы должны выполнить следующие три шага:
Вышеперечисленные шаги описывают минимум задач, которые вы должны решить для отображения диалогового окна. (Конечно, не всегда требуется проверять, какую кнопку нажал пользователь, но - почти всегда.) Как вы увидите позже, управление сложными диалоговыми окнами включает гораздо большее количество задач. Эти другие задачи включают в себя не только определение нажатой пользователем кнопки, но также передачу данных из и в диалоговое окно и проверку достоверности введенной пользователем информации.
Очень важно, чтобы вы поняли три вышеперечисленных шага, особенно шаг 1, в котором путаются многие программисты, в первый раз работающие с OWL. В конце концов, разве вы уже не создали свое диалоговое окно в Resource Workshop? Зачем вам снова создавать его в программе?
Если вы написали вашу программу без использования ObjectWindows, вам необходимо просто вызвать функцию DialogBox() Windows API, чтобы отобразить окно диалога. (Конечно, это означает и наличие диалоговой функции, обрабатывающей сообщения, которые Windows посылает диалоговому окну.) OWL, однако, предоставляет класс для работы с диалоговыми окнами, который выполняет большую часть черновой работы за вас - такой, например, как реакция на нажатие кнопок, передача данных в и из окна диалога, проверка вводимых пользователем данных, закрытие диалогового окна и многое другое.
Для использования преимуществ, предоставляемых классом диалогового окна, вы должны, конечно, создать экземпляр класса. Этот новый объект TDialog является своего рода оболочкой вокруг диалогового окна, которое вы создали с помощью Resource Workshop, избавляющей вас от ненужных деталей при работе с диалоговым окном. Выполнив шаг 1, вы имеете не только интерфейсный элемент диалоговое окно (который вы создали с помощью Resousce Workshop), но также и объект диалогового окна, который представляет этот интерфейсный элемент диалоговое окно и позволяет вам осуществлять доступ к функциям-членам TDialog OWL.
Следующий пример демонстрирует основы отображения и работы с диалоговым окном.
#include <owl\applicat.h> #include <owl\framewin.h> #include <owl\dialog.h> #include "pr19_1.rc" //Класс приложения class TApp: public TApplication { public: TApp():TApplication(){} void InitMainWindow(); }; //Класс основного окна class TWndw:public TFrameWindow { public: TWndw(TWindow *parent, const char far *title); protected: void CmTestDialog(); DECLARE_RESPONSE_TABLE (TWndw); }; DEFINE_RESPONSE_TABLE1 (TWndw, TFrameWindow) EV_COMMAND(CM_TESTDIALOG,CmTestDialog), END_RESPONSE_TABLE; TWndw::TWndw(TWindow *parent, const char far *title): TFrameWindow(parent,title) { // Добавить меню к главному окну. AssignMenu("MENU_1"); // Определить расположение и размеры окна. Attr.X=50; Attr.Y=50; Attr.W=GetSystemMetrics(SM_CXSCREEN)/4; Attr.H=GetSystemMetrics(SM_CXSCREEN)/5; } // TWndw::CmTestDialog() // Эта функция реагирует на команду Dialog/Test // меню Dialog. void TWndw::CmTestDialog() { // Создать окно диалога. TDialog *dialog = new TDialog(this, ADDRDLG); // Выполнить окно диалога. int result = dialog->Execute(); // Ответить на выбор пользователем кнопки. if (result == IDOK) MessageBox("Вы нажали кнопку OK", "Результат", MB_OK); else MessageBox("Вы нажали кнопку Отмена", "Результат", MB_OK); } void TApp::InitMainWindow() { TFrameWindow *wndw=new TWndw(0,"Пример диалогового окна"); SetMainWindow(wndw); } int OwlMain(int,char *[]) { return TApp().Run(); }
Файл ресурсов:
#ifndef WORKSHOP_INVOKED #include "windows.h" #endif #define ADDRDLG 100 #define IDC_NAME 101 #define IDC_ADDR 102 #define IDC_CITY 103 #define IDC_STATE 104 #define IDC_ZIP 105 #define IDC_PHONE 106 #define IDC_BIRTH 107 #define CM_EXIT 24310 #define CM_TESTDIALOG 108 #ifdef RC_INVOKED ADDRDLG DIALOG 39, 34, 239, 124 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Address Form" FONT 8, "MS Sans Serif" { EDITTEXT IDC_NAME, 42, 9, 188, 12, WS_BORDER | WS_TABSTOP EDITTEXT IDC_ADDR, 42, 26, 188, 12, WS_BORDER | WS_TABSTOP EDITTEXT IDC_CITY, 42, 44, 70, 12, WS_BORDER | WS_TABSTOP EDITTEXT IDC_STATE, 140, 45, 16, 12, WS_BORDER | WS_TABSTOP EDITTEXT IDC_ZIP, 180, 45, 50, 12, WS_BORDER | WS_TABSTOP EDITTEXT IDC_PHONE, 43, 67, 65, 12, WS_BORDER | WS_TABSTOP EDITTEXT IDC_BIRTH, 147, 67, 45, 12, WS_BORDER | WS_TABSTOP LTEXT "Name:", -1, 17, 11, 20, 8 LTEXT "Address:", -1, 9, 28, 29, 8 LTEXT "City:", -1, 23, 47, 17, 8 LTEXT "State:", -1, 116, 47, 20, 8 LTEXT "Zip:", -1, 163, 46, 13, 8 LTEXT "Phone:", -1, 16, 69, 24, 8 LTEXT "Birthday:", -1, 113, 69, 30, 8 DEFPUSHBUTTON "OK", IDOK, 76, 92, 33, 21 PUSHBUTTON "Cancel", IDCANCEL, 126, 93, 33, 21 } MENU_1 MENU { POPUP "&File" { MENUITEM "E&xit", CM_EXIT } POPUP "&Dialog" { MENUITEM "&Test Dialog...", CM_TESTDIALOG } } #endif
Когда вы запустите эту программу, появится пустое окно. Это окно содержит строку меню с пунктами File и Dialog. Для вывода диалогового окна, изображенного на рисунке 1, выберите опцию Test Dialog в пункте меню Dialog. Когда появится диалоговое окно, вы сможете ввести информацию в элементы управления редактированием окна диалога или просто нажать одну из кнопок, чтобы выйти из него. После выхода из диалогового окна программа отображает окно сообщений, показывающее выбранную кнопку.
Рис.1. Результат работы приложения
Эта программа охватывает три главных класса:
Класс приложения почти аналогичен классам, с которыми мы познакомились в предыдущих шагах. Класс главного окна содержит только одну функцию отклика на сообщение CmTestDialog(), которая реагирует на команду Test Dialog меню Dialog.
Хотя диалоговое окно является главной частью программы, оно не имеет собственного класса. (По крайней мере, в рамках данного примера.) Диалоговое окно полностью управляется функцией CmTestDialog() главного окна:
void TWndw::CmTestDialog() { // Создать окно диалога. TDialog *dialog = new TDialog(this, ADDRDLG); // Выполнить окно диалога. int result = dialog->Execute(); // Ответить на выбор пользователем кнопки. if (result == IDOK) MessageBox("Вы нажали кнопку OK", "Результат", MB_OK); else MessageBox("Вы нажали кнопку Отмена", "Результат", MB_OK); }
В первой строке вызывается конструктор TDialog, создающий объект диалогового окна в памяти. Первым аргументом конструктора является указатель на родителя окна диалога. В качестве родителя диалогового окна выступает главное окно, поэтому этим параметром является указатель this, который имеют все объекты C++. Вторым аргументом является идентификатор ресурса диалогового окна.
Поскольку диалоговое окно - не более, чем особый тип окна, класс TDialog порождается из TWindow и, таким образом, наследует все функции и данные класса. Хотя в данном примере окно диалога описывается только двумя строками программы, в действительности оно использует всю мощь объекта TDialog.
После создания объекта диалогового окна и связи его с реально существующим элементом диалогового окна (диалоговое окно создано в Resource Workshop) через идентификатор ресурса диалогового окна, CmTestDialog() активизирует диалоговые окна путем вызова функции Execute() диалогового окна. Execute() (и другие вызываемые ею функции OWL) вызывает Windows API для вывода диалогового окна на экран, управляет им и удаляет его с экрана по команде пользователя. Значение, возвращаемае Execute() - это идентификатор кнопки, которую нажал пользователь при выходе из окна диалога. CmTestDialog() использует это возвращаемое значение, чтобы определить, какое окно сообщения отображать.
На следующем шаге мы рассмотрим настройку класса TDialog.