Глава 5. Приложение
, основанное на диалоге (использование AppWizard)Рассмотрим, как создать приложение с диалогом в качестве главного окна, при помощи средства автоматизированной разработки приложений MFC AppWizard. При создании проекта с помощью этого средства необходимо ответить на ряд вопросов, которые и определяют тип и возможности создаваемого приложения.
Создание шаблона приложения
Сначала необходимо выбрать тип создаваемого приложения из предоставляемого списка: “Single document” (приложение с однооконным интерфейсом), “Multiple document” (приложение с многооконным интерфейсом) или “Dialog based” (приложение, основанное на диалоговой панели без главного окна). После выбора типа приложения “Dialog based” появится следующая диалоговая панель, предназначенная для определения основных свойств приложения.
В этой панели можно будет указать, будет ли у создаваемого приложения информационная диалоговая панель, справочная подсистема, трехмерные органы управления, возможности использования технологии OLE и коммуникации с помощью протокола TCP/IP. Здесь же можно задать заголовок главной диалоговой панели.
В следующей диалоговой панели можно либо указать на необходимость включения комментариев к создаваемому шаблону приложения, либо отменить этот режим. Здесь же можно отметить желаемый способ подключения библиотеки MFC - в виде статически или динамически подключаемой библиотеки.
На последней диалоговой панели можно задать имена для создаваемых системой AppWizard классов приложения.
После определения всех свойств приложения MFC AppWizard создаст проект, который можно сразу же оттранслировать и получить приложение, полностью готовое к запуску. После запуска приложения на экране появляется диалоговая панель с двумя кнопками “OK” и “Cancel” и статическим полем.
Проект dlg включает в себя ряд файлов, созданных системой AppWizard (см.
Приложение 1 ). Рассмотрим назначения этих файлов:Созданный при помощи AppWizard проект можно взять за основу, изменить его в соответствии с потребностями и задачами приложения. В диалоговую панель можно добавить новые органы управления, создать другие ресурсы. Изменять подготовленный проект можно с использованием средства ClassWizard (для добавления новых классов, новых методов и переменных для существующих классов, для создания методов-обработчиков сообщений и т.д.) и редактора ресурсов.
Главный класс приложения
Главный класс приложения CDlgApp определен в файле dlg.h и реализован в файле dlg.cpp.
Для класса CDlgApp описан конструктор, не имеющий параметров. Этот конструктор используется в момент запуска приложения для создания объекта класса CDlgApp.
Кроме конструктора, в классе CDlgApp переопределяется метод
InitInstance базового класса CWinApp . Каждый раз при запуске очередной копии приложения вызывается этот метод. Это единственный метод главного класса, который обязательно должен быть переопределен. Средство MFC AppWizard реализует переопределяемый метод InitInstance для различного типа пользовательского интерфейса (однооконный, многооконный, основанный на диалоге) по-разному.В данном случае в этом методе создается диалоговая панель, которая и будет выполнять роль пользовательского интерфейса приложения. Для этого сначала создается объект dlg класса CDlgDlg, который управляет диалоговой панелью. Затем адрес этого объекта присваивается элементу данных m_pMainWnd главного класса приложения.
После этого вызывается метод
DoModal для объекта dlg класса CDlgDlg. Он создает диалоговую панель и отображает ее на экране. Значение, выдаваемое методом DoModal , можно использовать для того, чтобы проанализировать результат работы пользователя с диалоговой панелью.Главный объект приложения
В файле dlg.cpp объявляется глобальный объект главного класса приложения. Именно с создания этого объекта и начинается работа приложения.
Объект класса
CWinApp (или класса, наследуемого от него) входит во все приложения, созданные с использованием MFC AppWizard, вне зависимости от пользовательского интерфейса этого приложения.Таблица сообщений класса
Таблица сообщений класса CDlgApp, созданная средством AppWizard, состоит из макрокоманд
BEGIN_MESSAGE_MAP и END_MESSAGE_MAP. Между ними располагаются макрокоманды, определяющие сообщения, обрабатываемые данным классом. Изначально в таблице определено только одно командное сообщение, имеющее идентификатор ID_HELP. Для его обработки вызывается метод OnHelp базового класса.Необработанные сообщения передаются на обработку базовому классу
CWinApp , так как он указан во втором параметре макрокоманды BEGIN_MESSAGE_MAP .Класс диалоговой панели
Класс главной диалоговой панели объявляется в файле dlgDlg.h и реализуется в файле dlgDlg.cpp.
Объявление класса
Класс CDlgDlg наследуется от базового класса
CDialog , определенного в библиотеке классов MFC. Конструктор класса имеет один необязательный параметр pParent, используемый для передачи индекса главного окна приложения. Роль главного окна выполняет сама диалоговая панель, поэтому параметр pParent не используется.Непосредственно после объявления конструктора класса следует объявление элементов данных класса, которые добавлены средствами MFC AppWizard. Не рекомендуется вручную изменять код приложения, расположенный между комментариями AFX_DATA, между которыми заключены эти объявления.
Далее AppWisard добавляет объявления переопределенных виртуальных методов базового класса. Сначала объявлен только метод
DoDataExchange , переопределенный для данной диалоговой панели. Этот метод применяется для связывания органов управления диалоговой панели с элементами управляющего ею класса.Практически со всеми приложениями связана пиктограмма, которая будет отображаться при минимизации приложения. Обычно эта пиктограмма определяется на этапе регистрации класса главного окна приложения. Приложение dlg не имеет настоящего главного окна - вместо него используется диалоговая панель. Поэтому отображение пиктограммы не происходит автоматически, и, следовательно, необходимо управлять ее отображением (идентификатор пиктограммы m_hIcon определен в классе CDlgDlg).
Диалоговая панель CDlgDlg будет обрабатывать ряд сообщений. Объявления обработчиков сообщений, созданных при помощи AppWizard, располагаются между комментариями AFX_MSG. После создания проекта в нем объявлены обработчики 4-х сообщений:
OnInitDialog, OnSysCommand, OnPaint и OnQueryDragIcon .Конструктор класса
Конструктор класса CDlgDlg вызывает конструктор базового класса CDialog . При этом ему передаются идентификатор диалоговой панели и идентификатор главного окна приложения.
В теле конструктора расположен блок AFX_DATA_INIT. В него ClassWizard будет добавлять код инициализации элементов данных класса CDlgDlg.
Конструктор также инициализирует m_hIcon, записывая в него идентификатор пиктограммы IDR_MAINFRAME:
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
Метод AfxGetAp возвращает указатель на объект главного класса приложения (в данном случае - указатель на объект theApp).
Метод DoDataExchange
Диалоговая панель имеет только кнопки и не имеет связанных с ними переменных. Однако метод
DoDataExchange переопределен. Фактически он не выполняет никакой работы. Единственное, что он делает, - это вызывает метод DoDataExchange базового класса CDialog .Если к диалоговой панели добавить новые органы управления и связать их средствами ClassWizard с элементами данных класса CDlgDlg, то в блоке AFX_DATA_MAP будут размещены вызовы функций DDX и DDV, необходимые для выполнения обмена данными.
Таблица сообщений
Таблица сообщений класса CDlgDlg содержит три макрокоманды, которые выполняют обработку сообщений
WM_SYSCOMMAND, WM_PAINT и WM_QUERYDRAGICON . Они расположены в блоке AFX_MSG_MAP, поэтому для управления ими используется ClassWizard.Метод OnInitDialog
При отображении диалоговой панели при помощи функций
DoModal, Create или CreateIndirect , функция диалоговой панели передается сообщение WM_INITDIALOG . Непосредственного доступа к функции диалога нет. Ее реализация содержится в классе CDialog .В ответ на сообщение
WM_INITDIALOG вызывается метод OnInitDialog , объявленный как виртуальный метод класса CDialog. Этот метод вызывается непосредственно перед выводом панели на экран.MFC AppWizard в реализацию этого метода добавил несколько действий: добавление строки к системному меню для вызова краткой справки о приложении, а также при помощи метода
SetIcon выбрал пиктограмму для приложения.Метод
OnInitDialog возвращает значение TRUE. Это означает, что фокус ввода будет установлен на первый орган управления диалоговой панели. Первый орган диалоговой панели можно выбрать в редакторе диалоговой панели.Если во время инициализации диалоговой панели метод OnInitDialog устанавливает фокус ввода другому органу управления, метод должен вернуть значение FALSE.
Метод OnSysCommand
Если при создании шаблонного приложения указать возможность отображения краткой справочной информации, то при этом средство AppWizard подготовит фрагмент кода, добавляющий соответствующую строку в системное меню, а также метод-обработчик
OnSysCommand сообщений от системного меню.Этот метод имеет два параметра - идентификатор строки системного меню, которую выбрал пользователь, и параметр, содержащий координаты мыши, если выбор сделан мышью.
Для обработки выбора стандартных пунктов меню переопределенный метод вызывается метод-обработчик базового класса (для обработки сообщений по умолчанию), а для добавленных пунктов выполняется специфическая обработка.
Метод OnPaint
Диалоговая панель в отличие от обычного окна не содержит встроенных средств отображения пиктограммы приложения. Приложение должно само заботиться об отображении пиктограммы - для этого переопределяется метод
OnPaint. В этом методе либо вызывается метод OnPaint базового класса, либо приложение само отображает пиктограмму, если оно в данный момент минимизировано.Метод OnQueryDragIcon
Пользователь может “перетащить” пиктограмму минимизированного приложения. Если пользователь производит это действие с пиктограммой окна, для класса которого не определена пиктограмма, то вызывается метод
OnQueryDragIcon . Этот метод должен вернуть идентификатор курсора мыши, который будет отображаться в момент “перетаскивания” пиктограммы окна.В переопределенном методе
OnQueryDragIcon средство AppWizard просто возвращает идентификатор пиктограммы приложения.