5762

Основы программирования под Windows с использованием MFC

Реферат

Информатика, кибернетика и программирование

Программирование под Windows с использованием MFC MFC - это базовый набор (библиотека) классов, написанных на языке С++ и предназначенных для упрощения и ускорения процесса программирования под Windows. Перед изучением библиотеки MFC и ее испол...

Русский

2012-12-19

208 KB

35 чел.

Программирование под Windows с использованием MFC

MFC – это базовый набор (библиотека) классов, написанных на языке С++ и предназначенных для упрощения и ускорения процесса программирования под Windows. Перед изучением библиотеки MFC и ее использованием для создания Windows-приложений, следует вспомнить, как работает сама Windows и каковы принципы взаимодействия программ с ней, какова структура типичной Windows-программы.

Преимущества использования MFC

Как уже упоминалось, MFC – это базовый набор (библиотека) классов, написанных на языке С++ и предназначенных для упрощения и ускорения процесса программирования для Windows. Библиотека содержит многоуровневую иерархию классов, насчитывающую около 200 членов. Они дают возможность создавать Windows-приложения на базе объектно-ориентированного подхода. С точки зрения программиста, MFC представляет собой каркас, на основе которого можно писать программы для Windows.

Библиотека MFC разрабатывалась для упрощения задач, стоящих перед программистом. Как известно, традиционный метод программирования под Windows требует написания достаточно длинных и сложных программ, имеющих ряд специфических особенностей. В частности, для создания только каркаса программы таким методом понадобится около 75 строк кода. По мере же увеличения сложности программы ее код может достигать поистине невероятных размеров. Однако та же самая программа, написанная с использованием MFC, будет примерно в три раза меньше, поскольку большинство частных деталей скрыто от программиста.

Одним из основных преимуществ работы с MFC является возможность многократного использования одного и того же кода. Так как библиотека содержит много элементов, общих для всех Windows-приложений, нет необходимости каждый раз писать их заново. Вместо этого их можно просто наследовать (говоря языком объектно-ориентированного программирования). Кроме того, интерфейс, обеспечиваемый библиотекой, практически независим от конкретных деталей, его реализующих. Поэтому программы, написанные на основе MFC, могут быть легко адаптированы к новым версиям Windows (в отличие от большинства программ, написанных обычными методами).

Еще одним существенным преимуществом MFC является упрощение взаимодействия с прикладным программным интерфейсом (API) Windows. Любое приложение взаимодействует с Windows через API, который содержит несколько сот функций. Внушительный размер API затрудняет попытки понять и изучить его целиком. Зачастую даже сложно проследить, как отдельные части API связанны друг с другом! Но поскольку библиотека MFC объединяет (путем инкапсуляции) функции API в логически организованное множество классов, интерфейсом становится значительно легче управлять.

Поскольку MFC представляет собой набор классов, написанных на языке С++, поэтому программы, написанные с использованием MFC, должна быть в то же время программами на С++. Для этого необходимо владеть соответствующими знаниями. Для начала необходимо уметь создавать собственные классы, понимать принципы наследования и уметь переопределять виртуальные функции. Хотя программы, использующие библиотеку MFC, обычно не содержат слишком специфических элементов из арсенала С++, для их написания тем не менее требуются солидные знания в данной области.

Замечание. Небольшое число классов, определенных в библиотеке, не связанно непосредственно с программированием под Windows. Это, в частности, классы, предназначенные для создания строк, управления файлами и обработки особых ситуаций. Иногда называемые классами общего назначения, они могут использоваться как Windows-, так и не- Windows-приложениями.

Обзор среды Microsoft Developer Studio

Студия разработчика фирмы Microsoft (Microsoft Developer Studio) - это интегрированная среда для разработки, позволяющая функционировать различным средам разработки, одна из которых Visual C++, другая - Visual J++. В дальнейшем будет идти речь только о среде разработки Visual C++.

В студии разработчика можно строить обычные программы на C и С++, создавать статические и динамические библиотеки, но основным режимом работы является создание Windows-приложений с помощью инструмента MFC AppWizard (Application Wizard - мастер приложений) и библиотеки базовых классов MFC (Microsoft Foundation Class Library). Такие приложения называются MFC-приложениями. Главная особенность этих Windows-приложений состоит в том, что они работают как совокупность взаимодействующих объектов, классы которых определены библиотекой MFC.

Библиотека MFC

Главная часть библиотеки MFC состоит из классов, используемых для построения компонентов приложения. С каждым MFC-приложением связывается определяющий его на верхнем уровне объект theApp, принадлежащий классу, производному от CWinApp.

Как правило, структура приложения определяется архитектурой Document-View (документ-облик). Это означает, что приложение состоит из одного или нескольких документов - объектов, классы которых являются производными от класса CDocument (класс "документ"). С каждым из документов связаны один или несколько обликов - объектов классов, производных от CView (класс "облик ") и определяющих облик документа.

Класс CFrameWnd ("окна-рамки") и производные от него определяют окна-рамки на дисплее. Элементы управления, создаваемые при проектировании интерфейса пользователя, принадлежат семейству классов элементов управления. Появляющиеся в процессе работы приложения диалоговые окна - это объекты классов, производных от CDialog.

Классы CView, CFrameWnd, CDialog и все классы элементов управления наследуют свойства и поведение своего базового класса CWnd ("окно"), определяющего по существу Windows-окно. Этот класс в свою очередь является наследником базового ласса CObject ("объект").

Одна из трудностей в понимании принципов устройства MFC-приложения, заключается в том, что объекты, из которых оно строится, наследуют свойства и поведение всех своих предков, поэтому необходимо знать базовые классы.

Архитектура приложения

У всех Windows-приложений фиксированная структура, определяемая функцией WinMain. Структура приложения, построенного из объектов классов библиотеки MFC, является еще более определенной.

Приложение состоит из объекта theApp, функции WinMain, и некоторого количества других объектов. Сердцевина приложения - объект theApp - отвечает за создание всех остальных объектов и обработку очереди сообщений. Объект theApp является глобальным и создается еще до начала работы функции WinMain. Работа функции WinMain заключается в последовательном вызове двух методов объекта theApp: InitInstance и Run. В терминах сообщений можно сказать, WinMain посылает объекту theApp сообщение InitInstance, которое приводит в действие метод InitInstance.

Получив сообщение InitInstance, theApp создает внутренние объекты приложения. Процесс создания выглядит как последовательное порождение одних объектов другими. Набор объектов, порождаемых в начале этой цепочки, определен структурой MFC практически однозначно - это главная рамка, шаблон, документ, облик. Их роли в работе приложения будут обсуждаться позже.

Следующее сообщение, получаемое theApp, - Run - приводит в действие метод Run. Оно как бы говорит объекту: "Начинай работу, начинай процесс обработки сообщений из внешнего мира". Объект theApp циклически выбирает сообщения из очереди и инициирует обработку сообщений объектами приложения.

Некоторые объекты имеют графический образ на экране, с которым может взаимодействовать пользователь. Эти интерфейсные объекты обычно связаны с Windows-окном. Среди них особенно важны главная рамка и облик. Именно им объект прежде всего распределяет сообщения из очереди через механизм Windows-окон и функцию Dispatch.

Когда пользователь выбирает команду меню окна главной рамки, то возникают командные сообщения. Они отправляются сначала объектом theApp объекту главная рамка, а затем обходят по специальному маршруту целый ряд объектов, среди которых первыми являются документ и облик, информируя их о пришедшей от пользователя команде.

При работе приложения возникают и обычные вызовы одними объектами методов других объектов. В объектно-ориентированной терминологии такие вызовы могут называться сообщениями. В Visual C++ некоторым методам приписан именно этот статус (например, методу OnDraw).

Важное значение имеют также объекты документ, облик и главная рамка. Здесь отметим только, что документ содержит данные приложения, облик организует представление этих данных на экране, а окно главной рамки - это окно, внутри которого размещены все остальные окна приложения.

Каркас приложения

Наследование - одна из фундаментальных идей объектно-ориентированного программирования. Именно этот механизм наследования позволяет программисту дополнять и переопределять поведение базового класса, не вторгаясь в библиотеку MFC, которая остается неизменной. Все изменения делаются в собственном производном классе. Именно в этом и заключается работа программиста.

Объекты, их которых состоит приложение, являются объектами классов, производных от классов библиотеки MFC. Разработка приложения состоит в том, что программист берет из библиотеки MFC классы CWinApp, CFrameWnd, CDocument, CView и т.д. и строит производные классы. Приложение создается как совокупность объектов этих производных классов. Каждый объект несет в себе как наследуемые черты, определяемые базовыми классами, так и новые черты, добавленные программистом. Наследуемые черты определяют общую схему поведения, свойственную таким приложениям. Новые же черты позволяют реализовать специфические особенности поведения приложения, необходимые для решения стоящей перед ним задачи.

При определении производного класса программист может:

  •  переопределить некоторые методы базового класса, причем те методы, что не были переопределены, будут наследоваться в том виде, в каком они существуют в базовом классе;
  •  добавить новые методы;
  •  добавить новые переменные.

Приложение, построенное на основе библиотеки MFC, - "айсберг", большая часть которого невидима, но является основой всего приложения. Часть приложения, лежащую в библиотеке MFC, - framework - называется каркасом приложения. Рассмотрим работу приложения как процесс взаимодействия между каркасом и частью приложения, разработанной программистом. Совершенно естественно, что в методах, определенных программистом, могут встречаться вызовы методов базового класса, что вполне можно рассматривать как вызов функции из библиотеки. Важнее, однако, что и метод производного класса, определенный программистом, может быть вызван из метода родительского класса. Другими словами, каркас и производный класс в этом смысле равноправны - их методы могут вызывать друг друга. Такое равноправие достигается благодаря виртуальным методам и полиморфизму, имеющимся в арсенале объектно-ориентированного программирования.

Если метод базового класса объявлен виртуальным и разработчик переопределил его в производном классе, это значит, что при вызове данного метода в некоторой полиморфной функции базового класса в момент исполнения будет вызван метод производного класса и, следовательно, каркас вызывает метод, определенный программистом. Точнее говоря, обращение к этому методу должно производиться через ссылку на производный объект либо через объект, являющийся формальным параметром и получающий при вызове в качестве своего значения объект производного класса. Когда вызывается виртуальный метод М1, переопределенный разработчиком, то согласно терминологии Visual C++, каркас посылает сообщение М1 объекту производного класса, а метод М1 этого объекта обрабатывает это сообщение. Если сообщение М1 послано объекту производного класса, а обработчик этого сообщения не задан программистом, объект наследует метод М1 ближайшего родительского класса, в котором определен этот метод. Если же обработчик такого сообщения создан программистом, он автоматически отменяет действия, предусмотренные родительским классом в отсутствие этого обработчика.

Каркас приложений

С Visual C++ тесно связано еще одно понятие - каркас приложений, которое близко и созвучно понятию каркаса приложения, но в отличие от него относится не к одному конкретному приложению, а к библиотеке, с помощью которой строятся многие приложения. Каркас приложений - это библиотека классов, из которых программист берет не только набор классов, играющих роль дополнительных типов данных, но и классы, служащие строительными блоками приложения на самом верхнем уровне. С этой точки зрения, каркас приложения является частью каркаса приложений, относящейся к данному приложению. Примеры каркасов приложений - библиотеки классов MFC и OWL.

Проект приложения

О принципах устройства приложения рассказывалось выше. Теперь рассмотрим, как оно создается с помощью Visual C++. Сначала разберем одно важное понятие - проект. До сих пор приложение рассматривалось, как только как совокупность объектов базовых и производных классов. Но для обеспечения работы приложения требуется нечто большее - наряду с описанием классов необходимо описание ресурсов, связанных с приложением, нужна справочная система и т.п. Термин "проект" как раз и используется, когда имеется в виду такой более общий взгляд на приложение.

В среде Visual C++ можно строить различные типы проектов. Такие проекты после их создания можно компилировать и запускать на исполнение. Фирма Microsoft разработала специальный инструментарий, облегчающий и ускоряющий создание проектов в среде Visual C++. Например, мастер MFC AppWizard (exe) позволяет создать проект Windows-приложения которое имеет однодокументный, многодокументный или диалоговый интерфейс и использует библиотеку MFC.

Создаваемый остов приложения составлен так, что в дальнейшей работе с проектом можно использовать другое инструментальное средство - ClassWizard (мастер классов), предназначенное для создания остовов новых производных классов. Еще одно основное назначение ClassWizard в том, что он создает остовы для переопределяемых методов. Он позволяет показать все сообщения, приходящие классу, и создать остов обработчика любого из этих сообщений. Это только две основные функции ClassWizard. Он не всесилен, но его возможности довольно велики.

Использование средств разработки

В состав компилятора Microsoft Developer Studio встроены средства, позволяющие программисту облегчить разработку приложений. В первую очередь к ним относятся MFC AppWisard, ClassWizard и редактор ресурсов.

Благодаря MFC AppWizard среда разработчика позволяет быстро создавать шаблоны новых приложений. При этом программисту не приходится писать ни одной строчки кода. Достаточно ответить на ряд вопросов, касающихся того, какое приложение требуется создать, и исходные тексты шаблона приложения вместе с файлами ресурсов готовы. Эти тексты можно оттранслировать и получить готовый загрузочный модуль приложения.

Конечно, никакие средства автоматизированной разработки не смогут создать программу полностью без участия программиста. Прикладную часть приложения придется разрабатывать ему.

Для создания ресурсов приложения предназначен редактор ресурсов. Он позволяет быстро создавать новые меню, диалоговые панели, добавлять кнопки к панели управления toolbar и т.д.

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

Типы мастеров проектов

В среде Visual C++ можно строить различные типы проектов. Такие проекты после их создания можно компилировать и запускать на исполнение. Фирма Microsoft разработала специальный инструментарий, облегчающий и ускоряющий создание проектов в среде Visual C++.

Рассмотрим некоторые типы проектов, которые можно создавать при помощи различных средств (мастеров проектов) Microsoft Visual C++:

MFC AppWizard (exe) – при помощи мастера приложений можно создать проект Windows-приложения которое имеет однодокументный, многодокументный или диалоговый интерфейс. Однодокументное приложеие может предоставлять пользователю в любой момент времени работать только с одним файлом. Многодокументное приложение, напротив, может одновременно представлять несколько документов, каждый в собственном окне. Пользовательский интерфейс диалогового приложения представляет собой единственное диалоговое окно.

MFC AppWizard (dll) – этот мастер приложений позволяет создать структуру DLL, основанную на MFC. При помощи него можно определить характеристики будующей DLL.

AppWizard ATL COM – это средство позволяет создать элемент управления ActiveX или сервер автоматизации, используя новую библиотеку шаблонов ActiveX (ActiveX Template Library - ATL). Опции этого мастера дают возможность выбрать активный сервер (DLL) или исполняемый внешний сервер (exe-файл).

Custom AppWizard – при помощи этого средства можно создать пользовательские мастера AppWizard. Пользовательский мастер может базироваться на стандартных мастерах для приложений MFC или DLL, а также на существующих проектах или содержать только определеямые разработчиком шаги.

DevStudio Add-in Wizard – мастер дополнений позволяет создавать дополнения к Visual Studio. Библиотека DLL расширений может поддерживать панели инструментов и реагировать на события Visual Studio.

MFC ActiveX ControlWizard - мастер элементов управления реализует процесс создания проекта, содержащего один или несколько элементов управления ActiveX, основанных на элементах управления MFC.

Win32 Application – этот мастер позволяет создать проект обычного Window-приложения. Проект создается незаполненным, файлы с исходным кодом в него следует добавлять вручную.

Win32 Console Application – мастер создания проекта консольного приложения. Консольная приложение – это программа, которая выполняется из командной cтроки окна DOS или Windows и не имеет графического интерфейса (окон). Проект консольного приложения создается пустым, предполагая добавление файлов исходного текста в него вручную.

Win32 Dynamic-Link Library – создание пустого проекта динамически подключаемой библиотеки. Установки компилятора и компоновщика будут настроены на создание DLL. Исходные файлы следует добавлять вручную.

Win32 Static Library – это средство создает пустой проект, предназначенный для генерации статической (объектной) библиотеки. Файлы с исходным кодом в него следует добавлять вручную.

Преимущества мастеров проектов

Рассмотрим преимущества использования мастеров в процессе создания приложений. Прежде всего, нужно отметить, что создание проекта - это не только творчество, но и большой объем технической работы, требующей внимания и аккуратности.

Например, все Windows-приложения имеют достаточно общую структуру, и, следовательно, можно построить некоторые шаблонные заготовки, подходящие для того или иного типа проектов. Построению таких заготовок способствует то, что приложения, создаваемые на основе MFC, строятся из элементов фиксированных классов. Логическим развитием этой идеи было введение специальных классов и специальной архитектуры построения приложения, которая подходила бы широкому классу приложений. О такой архитектуре уже упоминалось, когда речь шла о библиотеке MFC, - это архитектура Document-View. Она является основной, но не единственной при построении проектов в среде Visual C++.

Суть этой архитектуры в том, что работу многих приложений можно рассматривать как обработку документов. При этом можно отделить сам документ, отвечающий за представление и хранение данных, от образа этого документа, видимого на экране и допускающего взаимодействие с пользователем, который просматривает и (или) редактирует документ. В соответствии с этой архитектурой библиотека MFC содержит два семейства классов, производных от базовых классов CDocument и CView.

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

Начальная заготовка - остов приложения - создается в диалоге с пользователем инструментальным средством AppWizard. В процессе диалога пользователь определяет тип и характеристики проекта, который он хочет построить. Определив, какие классы из MFC необходимы для этого проекта, AppWizard строит остовы всех нужных производных классов. Построенный AppWizard остов приложения содержит все необходимые файлы для создания стартового приложения, которое является законченным приложением и обладает разумными функциональными свойствами, общими для целого класса приложений. Естественно, никаких специфических для данного приложения свойств остов не содержит. Они появятся на следующем этапе, когда программист начнет работать с остовом, создавая из заготовки свое собственное приложение. Тем не менее стартовое приложение можно транслировать и запускать на исполнение.

Термин остов (приложения, класса, функции) применяется для заготовок, создаваемых инструментальными средствами AppWizard и ClassWizard. Нужно подчеркнуть - остов приложения и каркас приложения - разные понятия.

Создаваемый остов приложения составлен так, что в дальнейшей работе с проектом можно использовать другое инструментальное средство - ClassWizard (мастер классов).

Обзор возможностей ClassWizard

Средство ClassWizard предоставляет широкий спектр услуг. Он позволяет не только добавлять к существующему классу новые методы и данные.

Создание нового класса. При помощи ClassWizard можно добавить новый класс, созданный на основе базовых классов. В качестве базового класса можно использовать классы, наследованные от класса CCmdTarget или класса CRecordset. Для наследования классов от других базовых классов использовать средства ClassWizard нельзя. Такие классы надо создавать вручную, непосредственно в текстовом редакторе.

Объекты, порожденные от класса CCmdTarget, могут обрабатывать сообщения Windows и команды, поступающие от меню, кнопок, акселераторов. Класс CCmdTarget и другие наследованные от него классы имеют таблицу сообщений (Message Map) - набор макрокоманд, позволяющий сопоставить сообщения Windows и команды метода класса.

Полученная заготовка класса полностью работоспособна. Ее можно дополнить по своему усмотрению новыми методами и данными. Эту работу можно выполнить вручную, но гораздо лучше и проще воспользоваться услугами ClassWizard. За счет использования ClassWizard процедура создания собственного класса значительно ускоряется и уменьшается вероятность совершить ошибку во время объявления методов.

Включение в класс новых методов. Очень удобно использовать ClassWizard для включения в состав класса новых методов. Можно добавлять к классу методы, служащие для обработки сообщений Windows и команд от объектов, а также методы, переопределяющие виртуальные методы базовых классов.

ClassWizard не только позволяет добавить в класс новые методы, но и удалить их. ClassWizard самостоятельно удалит объявление метода из класса.

Включение в класс новых элементов данных. ClassWizard позволяет включать в класс не только новые методы, но и элементы данных, связанные с полями диалоговых панелей, форм просмотра и форм для просмотра записей баз данных и полей наборов записей. ClassWizard использует специальные процедуры, чтобы привязать созданные им элементы данных к класса к полям диалоговых панелей. Эти процедуры носят названия "обмен данными диалоговой панели" и "проверка данных диалоговой панели" (Dialog Data Exchange and Dialog Data Validation - DDX/DDV). Чтобы привязать поля из наборов записей к переменным, используется процедура обмена данными с полями записей (Record Field Exchange - RFX).

Процедуры DDX/DDV и RFX значительно упрощают программисту работу с диалоговыми панелями. Они позволяют связать поля диалоговых панелей и переменные. Когда пользователь редактирует поля диалоговых панелей, процедуры DDV проверяют введенные значения и блокируют ввод запрещенных значений. Затем процедуры DDX автоматически копируют содержимое полей диалоговых панелей в привязанные к ним элементы данных класса. И наоборот, когда приложение изменяет элементы данных класса, привязанные к полям диалоговой панели, процедуры DDX могут сразу отобразить новые значения полей на экране компьютера.

Имена, используемые в MFC

Библиотека MFC содержит большое количество классов, структур, констант и т.д. Для того, чтобы текст MFC-приложений был более легким для понимания, принято применять ряд соглашений для используемых имен и комментариев.

Названия всех классов и шаблонов классов библиотеки MFC начинаются с заглавной буквы C. При наследовании классов от классов MFC можно давать им любые имена. Рекомендуется начинать их названия с заглавной буквы C. Это сделает исходный текст приложения более ясным для понимания.

Чтобы отличить элементы данных, входящих в класс, от простых переменных, их имена принято начинать с префикса m_. Названия методов классов, как правило, специально не выделяются, но обычно их начинают с заглавной буквы.

Библиотека MFC включает в себя, помимо классов, набор служебных функций. Названия этих функций начинаются с символов Afx, например AfxGetApp. Символы AFX являются сокращением от словосочетания Application FrameworkX, означающих основу приложения, его внутреннее устройство.

Символы AFX встречаются не только в названии функций MFC. Многие константы, макрокоманды и другие символы начинаются с этих символов. В общем случае AFX является признаком, по которому можно определить принадлежность того или иного объекта (функция, переменная, ключевое слово или символ) к библиотеке MFC.

Когда приложение разрабатывается средствами MFC AppWizard и ClassWizard, они размещают в исходном тексте приложения комментарии следующего вида:

//{{AFX_

...

//}}AFX_

Такие комментарии образуют блок кода программы, который управляется только средствами MFC AppWizard и ClassWizard. Пользователь не должен вручную вносить изменения в этом блоке. Для этого необходимо употреблять средства ClassWizard.

В следующей таблице представлено краткое описание некоторых блоков //{{AFX_:

Блок

Описание

//{{AFX_DATA
//}}AFX_DATA

Включает объявление элементов данных класса. Используется в описании классов диалоговых панелей.

//{{AFX_DATA_INIT
//}}AFX_DATA_INIT

Включает инициализацию элементов данных класса. Используется в файле реализации классов диалоговых панелей.

//{{AFX_DATA_MAP
//}}AFX_DATA_MAP

Включает макрокоманды DDX, предназначенные для связывания элементов данных класса и органов управления диалоговых панелей. Используется в файле реализации классов диалоговых панелей.

//{{AFX_MSG
//}}AFX_MSG

Включает описание методов, которые предназначены для обработки сообщений. Этот блок используется при описании класса.

//{{AFX_MSG_MAP
//}}AFX_MSG_MAP

Включает макрокоманды таблицы сообщений класса. Используются совместно с AFX_MSG.

//{{AFX_VIRTUAL
//}}AFX_VIRTUAL

Включает описание переопределенных виртуальных методов класса. Блок AFX_VIRTUAL используется при описании класса.

MFC AppWizard и ClassWizard помогают разрабатывать приложения. Они создают все классы и методы, необходимые для его работы. Программисту остается дописать к ним свой код. В тех местах, где можно вставить свой код, MFC AppWizard и ClassWizard, как правило помещают комментарии:

//TODO:

Глава 2. Краткий обзор классов MFC

  •  Самый базовый класс библиотека MFC (класс CObject)
  •  Основа структуры приложения (класс CCmdTarget)
    •  Подзадачи приложения (классы CWinThread и CWinApp)
    •  Документ приложения (класс CDocument)
    •  Шаблон документов (классы CDocTemplate, CSingleDocTemplate и CMultiDocTemplate)
    •  Окна (класс CWnd)
  •  Массивы, списки, словари
  •  Файловая система (класс CFile)
  •  Контекст отображения (класс CDC)
  •  Объекты графического интерфейса (класс CGdiObject)
  •  Меню (класс CMenu)
  •  Другие классы
  •  Классы, не имеющие базового класса

Библиотека классов MFC содержит большое количество разнообразных классов. Каждый класс, как правило, содержит от нескольких единиц до нескольких десятков различных методов и элементов данных. Для изучения иерархии классов MFC можно воспользоваться документацией или справочной системой среды Microsoft Developer Studio.

Рассмотрим кратко назначение некоторых основных классов библиотеки MFC и их связь друг с другом.

Самый базовый класс библиотека MFC (класс CObject)

Подавляющее большинство классов MFC наследовано от базового класса CObject, лежащего в основе всей иерархии классов этой библиотеки. Методы и элементы данных класса CObject представляют наиболее общие свойства наследованных из него классов MFC.

Класс CObject, а также все классы, наследованные от него, обеспечивают возможность сохранения объектов класса в файлах на диске с их последующим восстановлением.

Для объектов классов, наследованных от базового класса CObject, уже во время работы приложения можно получить разнообразную информацию о классе объекта.

Ряд методов класса CObject предназначен для получения дампа объектов класса во время отладки приложения. Эта особенность класса может ускорить процесс поиска ошибок в приложении.

Основа структуры приложения (класс CCmdTarget)

Непосредственно от класса CObject наследуются ряд классов, которые сами являются базовыми для остальных классов MFC. В первую очередь это класс CCmdTarget, представляющий основу структуры любого приложения. Основной особенностью класса CCmdTarget и классов, наследованных от него, является то, что объекты этих классов могут получать от операционной системы сообщения и обрабатывать их. От класса CCmdTarget наследуется несколько классов, краткое описание которых следует ниже.

Подзадачи приложения (классы CWinThread и CWinApp)

От класса CCmdTarget наследуется класс CWinThread, представляющий подзадачи приложения. Простые приложения, которые будут рассматриваться дальше, имеют только одну подзадачу. Эта подзадача, называемая главной, представляется классом CWinApp, наследованным от класса CWinThread.

Документ приложения (класс CDocument)

Большинство приложений работают с данными или документами, хранимыми на диске в отдельных файлах. Класс CDocument, наследованный от базового класса CCmdTarget, служит для представления документов приложения.

Шаблон документов (классы CDocTemplate, CSingleDocTemplate и CMultiDocTemplate)

Еще один важный класс, наследуемы от CCmdTarget, называется CDocTemplate. От этого класса наследуется два класса: CSingleDocTemplate и CMultiDocTemplate. Все эти классы предназначены для синхронизации и управления основными объектами , представляющими приложение, - окнами, документами и используемыми ими ресурсами.

Окна (класс CWnd)

Практически все приложения имеют пользовательский интерфейс, построенный на основе окон. Это может быть диалоговая панель, одно окно или несколько окон, связанных вместе. Основные свойства окон представлены классом CWnd, наследованным от класса CCmdTarget.

Программисты очень редко создают объекты класса CWnd. Класс CWnd сам является базовым классом для большого количества классов, представляющих разнообразные окна. Перечислим классы, наследованные от базового класса CWnd.

Обрамляющие окна (класс CFrameWnd). Класс CFrameWnd представляет окна, выступающие в роли обрамляющих окон, в том числе главные окна приложений. От этого класса также наследуются классы CMDIChildWnd и CMDIFrameWnd, используемые для отображения окон многооконного интерфейса MDI. Класс CMDIFrameWnd представляет главное окно приложения MDI, а класс CMDIChildWnd - его дочерние окна MDI. Класс CMiniFrameWnd применяется для отображения окон уменьшенного размера. Такие окна обычно используются для отображения в них панели управления.

Окна органов управления. Для работы с органами управления (кнопки, полосы прокрутки, редакторы текста и т.д.) в библиотеке MFC предусмотрены специальные классы, наследованные непосредственно от класса CWnd. Перечислим эти классы:

  •  CAnimate - используется для отображения видеоинформации.
  •  CBitmapButton - кнопка с рисунком.
  •  CButton - кнопка.
  •  CComboBox - список с окном редактирования.
  •  CEdit - поле редактирования.
  •  CHeaderCtrl - заголовок для таблицы.
  •  CHotKeyCtrl - предназначен для ввода комбинации клавиш акселераторов.
  •  CListBox - список.
  •  CListCtrl - может использоваться для отображения списка пиктограмм.
  •  CProgressCtrl - линейный индикатор.
  •  CPropertySheet - блокнот. Может состоять из нескольких страниц.
  •  CRichEditControl - окно редактирования, в котором можно редактировать форматированный текст.
  •  CScrollBar - полоса просмотра.
  •  CSliderCtrl - движок.
  •  CSpinButtonCtrl - обычно используется для увеличения или уменьшения значения какого-либо параметра.
  •  CStatic - статический орган управления.
  •  CTabCtrl - набор "закладок".
  •  CToolBarCtrl - панель управления.
  •  CToolTipCtrl - маленькое окно, содержащее строку текста.
  •  CTreeCtrl - орган управления, который позволяет просматривать иерархические структуры данных.

Управляющие панели (классы CControlBar, CToolBar, CStatusBar, CDialogBar). Класс CControlBar и классы, наследуемые от него, предназначены для создания управляющих панелей. Такие панели могут содержать различные органы управления и отображаются, как правило, в верхней или нижней части главного окна приложения.

Так, класс CToolBar предназначен для создания панели управления. Эта панель обычно содержит ряд кнопок, дублирующих действие меню приложения.

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

Большие возможности представляет управляющая панель, созданная на основе класса CDialogBar. Такая панель использует обычный шаблон диалоговой панели, которую можно разработать в редакторе ресурсов Visual C++.

Окна просмотра (класс CView и классы, наследованные от него). Большой интерес представляют класс CView и классы, наследуемые от него. Эти классы представляют окно просмотра документов приложения. Именно окно просмотра используется для вывода на экран документа, с которым работает приложение. Через это окно пользователь может изменять документ.

Разрабатывая приложение, программисты наследуют собственные классы просмотра документов либо от базового класса CView, либо от одного из нескольких порожденных классов, определенных в библиотеке MFC.

Классы, наследованные от CCtrlView, используют для отображения готовые органы управления. Например, класс CEditView использует орган управления edit (редактор).

Класс CScrollView представляет окно просмотра, которое имеет полосы свертки. В классе определены специальные методы, управляющие полосами просмотра.

Класс CFormView позволяет создать окно просмотра документа, основанное на диалоговой панели. От этого класса наследуется еще два класса CRecordView и CDaoRecordView. Эти классы используются для просмотра записей баз данных.

Диалоговые панели (класс CDialog и классы, наследованные от него ). От базового класса наследуются классы, управляющие диалоговыми панелями. Если необходимо создать диалоговую панель, можно наследовать класс от CDialog.

Вместе с диалоговыми панелями обычно используется класс CDataExchange. Класс CDataExchange обеспечивает работу процедур обмена данными DDX (Dialog Data Exchange) и проверки данных DDV (Dialog Data Validation), используемых для диалоговых панелей. В отличие от CDialog класс CDataExchange не наследуется от какого-либо другого класса.

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

Чтобы создать стандартный диалог, можно просто определить объект соответствующего класса. Дальнейшее управление такой панелью осуществляется методами класса.

Массивы, списки, словари

В состав MFC включен целый набор классов, предназначенных для хранения информации в массивах, списках и словарях. Все эти классы наследованы от базового класса CObject.

Несмотря на то, что в языке C определено понятие массива, классы MFC обеспечивают более широкие возможности. Например, можно динамически изменять размер массива, определенного с помощью соответствующего класса.

Для представления массивов предназначены следующие классы:

  •  CByteArray - байты.
  •  CDWordArray - двойные слова.
  •  CObArray - указатели на объекты класса CObject.
  •  CPtrArray - указатели типа void.
  •  CStringArray - объекты класса CString.
  •  CUIntArray - элементы класса unsigned integer или UINT.
  •  CWordArray - слова.

Для решения многих задач применяются такие структуры хранения данных, как списки. MFC включает ряд классов, наследованных от базового класса CObject, которые представляют программисту готовое для создания собственных списков. В этих классах определены все методы, необходимые при работе со списками, - добавление нового элемента, вставка нового элемента, определение следующего или предыдущего элемента в списке, удаление элемента и т.д.

Перечислим классы списков, которые позволяют построить списки из элементов любых типов любых классов:

  •  CObList - указатели на объекты класса CObject.
  •  CPtrList - указатели типа void.
  •  CStringList - объекты класса CString.

В библиотеке MFC определена еще одна группа классов, позволяющая создавать словари. Словарь представляет собой таблицу из двух колонок, устанавливающих соответствие двух величин. Первая величина представляет ключевое значение и записывается в первую колонку, а вторая - связанное с ней значение, хранящееся во второй колонке. Словарь позволяет добавлять в него пары связанных величин и осуществлять выборку значений по ключевому слову.

Для работы со словарями используются классы:

  •  CMapPtrToPtr - ключевое слово - указатель типа void, связанное с ним значение - указатель типа void.
  •  CMapPtrToWord - ключевое слово - указатель типа void, связанное с ним значение - слово.
  •  CMapStringToOb - ключевое слово - объекты класса CString, связанное с ним значение - указатель на объекты класса CObject.
  •  CMapStringToPtr - ключевое слово - объекты класса CString, связанное с ним значение - указатель типа void.
  •  CMapStringToString - ключевое слово - объекты класса CString, связанное с ним значение - на объекты класса CObject.
  •  CMapWordToOb - ключевое слово - слово, связанное с ним значение - указатель на объекты класса CObject.
  •  CMapWordToPtr- ключевое слово - слово, связанное с ним значение - указатель типа void.

Файловая система (класс CFile)

Библиотека MFC включает класс для работы с файловой системой компьютера. Он называется CFile и также наследуется от базового класса CObject. Непосредственно от класса CFile наследуется еще несколько классов - CMemFile, CStdioFile, CSocketFile.

При работе с файловой системой может потребоваться получить различную информацию о некотором файле, например, дату создания, размер и т.д. Для хранения этих данных предназначен специальный класс CFileStatus. Класс CFileStatus - один из немногих классов, которые не наследуются от базового класса CObject.

Контекст отображения (класс CDC)

Для отображения информации в окне или на любом другом устройстве приложение должно получать так называемы контекст отображения. Основные свойства контекста отображения определены в классе CDC. От него наследуется 4 различных класса, представляющие контекст отображения различных устройств.

Дадим краткое описание классов, наследованных от CDC:

  •  CClientDC - контекст отображения, связанный с внутренней областью окна (client area). Для получения контекста конструктор класса вызывает функцию программного интерфейса GetDC, а деструктор - функцию ReleaseDC.
  •  CMetaFileDC - класс предназначен для работы с метафайлами.
  •  CPaintDC - конструктор класса CPaintDC для получения контекста отображения вызывает метод CWnd::BeginPaint, деструктор - метод CWnd::EndPaint. Объекты данного класса можно использовать только при обработке сообщения WM_PAINT. Это сообщение обычно обрабатывает метод OnPaint.
  •  CWindowDC - контекст отображения, связанный со всем окном. Для получения контекста конструктор класса вызывает функцию программного интерфейса GetWindowDC, а деструктор - функцию ReleaseDC.

Объекты графического интерфейса (класс CGdiObject)

Для отображения информации используются различные объекты графического интерфейса - GDI-объекты. Для каждого из этих объектов библиотека MFC содержит описывающий его класс, наследованный от базового класса CGdiObject.

Для работы с GDI-объектами используются классы:

  •  CBitmap - растровое изображение bitmap.
  •  CBbrush - кисть.
  •  CFont - шрифт.
  •  CPalette - палитра цветов.
  •  CPen - -перо.
  •  CRgn - область внутри окна.

Меню (класс CMenu)

Практически каждое приложение имеет собственное меню. Оно, как правило, отображается в верхней части главного окна приложения. Для управления меню в состав MFC включен специальный класс CMenu, наследованный непосредственно от базового класса CObject.

Для управления меню и панелями используется также класс CCmdUI. Этот класс не наследуется от базового класса CObject.

Объекты класса CCmdUI создаются, когда пользователь выбирает строку меню или нажимает кнопки панели управления. Методы класса CCmdUI позволяют управлять строками меню и кнопками панели управления. Например, существует метод, который делает строку меню неактивной.

Другие классы

В MFC включено несколько классов, обеспечивающих поддержку приложений, работающих с базами данных. Это такие классы, как CDataBase, CRecordSet, CDaoDataBase. CDaoRecordSet, CDaoQueryDef, CDaoTableDef, CDaoWorkSpace, CLongBinary, CFieldExchange и CDaoFieldExchange.

Библиотека MFC позволяет создавать многозадачные приложения. Для синхронизации отдельных задач приложения предусмотрен ряд специальных классов. Все они наследуются от класса CSyncObject, представляющий собой абстрактный класс.

В некоторых случаях требуется, чтобы участок программного кода мог выполняться только одной задачей. Такой участок называют критической секцией кода. Для создания и управления критическими секциями предназначены объекты класса CCriticalSection.

Объекты класса CEvent представляют событие. При помощи событий одна задача приложения может передать сообщение другой.

Объекты класса CMutex позволяют в данный момент предоставить ресурс в пользование одной только задаче. Остальным задачам доступ к ресурсу запрещается.

Объекты класса CSemafore представляют собой семафоры. Семафоры позволяют ограничить количество задач, которые имеют доступ к какому-либо ресурсу.

Для программистов, занимающихся сетевыми коммуникациями, в состав библиотеки MFC включены классы CAsyncSocket и наследованный от него класс CSocket. Эти классы облегчают задачу программирования сетевых приложений.

Кроме уже описанных классов библиотека MFC включает большое количество классов, предназначенных для организации технологии OLE.

Классы, не имеющие базового класса

Кроме классов, наследованных от базового класса CObject, библиотека MFC включает ряд самостоятельных классов. У них нет общего базового класса, и имеют различное назначение.

Несколько классов, которые не наследуются от базового класса CObject, уже упоминались. К ним относятся классы CCmdUI, CFileStatus, CDataExchange, CFieldExchange и CDaoFieldExchange.

Простые классы. Библиотека MFC содержит классы, соответствующие объектам типа простых геометрических фигур, текстовых строк и объектам, определяющим дату и время:

  •  CPoint - объекты класса описывают точку.
  •  CRect - объекты класса описывают прямоугольник.
  •  CSize - объекты класса определяют размер прямоугольника.
  •  CString - объекты класса представляют собой текстовые строки переменной длины.
  •  CTime - объекты класса служат для хранения даты и времени. Большое количество методов класса позволяет выполнять над объектами класса различные преобразования.
  •  CTimeSpan - объекты класса определяют период времени.

Архивный класс (класс CArchive). Класс CArchive используется для сохранения и восстановления состояния объектов в файлах на диске. Перед использованием объекта класса CArchive он должен быть привязан к файлу - объекта класса CFile.

Информация о классе объекта (структура CRuntimeClass). Во многих случаях бывает необходимо уже во время работы приложения получать информацию о классе и его базовом классе. Для этого любой класс, наследованный от базового класса CObject, связан со структурой CRuntimeClass. Она позволяет определить имя класса объекта, размер объекта в байтах, указатель на конструктор класса, не имеющий аргументов, и деструктор класса. Можно также узнать подобную информацию о базовом классе и некоторые дополнительные сведения.

Отладка приложения (классы CDumpObject, CMemoryState). В отладочной версии приложения можно использовать класс CDumpContext. Он позволяет выдавать состояние различных объектов в текстовом виде.

Класс CMemoryState позволяет локализовать проблемы, связанные с динамическим выделением оперативной памяти. Такие проблемы обычно возникают, когда пользователь выделяет память, применяя оператор new, а затем забывает вернуть эту память операционной системе.

Печать документа (класс CPrintInfo). Класс CPrintInfo предназначен для управления печатью документов на принтере. Когда пользователь отправляет документ на печать или выполняет предварительный просмотр документа перед печатью, создается объект класса CPrintInfo. Он содержит различную информацию о том, какие страницы документа печатаются , и т.д.

Глава 3. Простейшие MFC-приложения

  •  Приложение без главного окна
  •  Приложение с главным окном
  •  Обработка окном сообщений
    •  Группы сообщений
    •  Таблица сообщений
    •  Приложение, обрабатывающее сообщения

Самые простые приложения с использованием библиотеки классов MFC можно создавать в Microsoft Developer Studio без применения автоматизированных средств разработки приложений MFC AppWizard. Необходимо только создать проект типа Win32 Application и включить в его установки поддержку библиотеки MFC.

Приложение без главного окна

Самые простые приложения с использованием библиотеки классов MFC можно создавать без применения автоматизированных средств разработки приложений MFC AppWizard. Создадим приложение, отображающее на экране маленькую диалоговую панель, которая содержит строку текста. В этом приложении используется единственный класс, наследованный от базового класса CWinApp. Приведем исходный текст приложения:

Файл first.cpp

#include <afxwin.h> // Включаемый файл для MFC

// Класс CFirstApp - главный класс приложения.

// Наследуется от базового класса CWinApp.

 class CFirstApp:public CWinApp

{

public:

 // Переопределение метода InitInstance,

 // предназначенного для инициализациии приложения.

 virtual BOOL InitInstance();

};

// Создание объекта приложения класса CFirstApp.

CFirstApp theApp;

// Метод InitInstance

// Переопределение виртуального метода InitInstance класса CWinApp.

// Он вызывается каждый раз при запуске приложения.

 BOOL CFirstApp::InitInstance()

{

 AfxMessageBox("First MFC-application");

 return FALSE;

}

В этом приложении определен только один класс - CFirstApp, наследованный от базового класса CWinApp. В класс CFirstApp входит метод InitInstance. Кроме того, определена одна глобальная переменная - theApp.

Для использования в приложении классов или функций библиотеки MFC необходимо включить эту библиотеку в проект приложения. Программные коды библиотеки классов MFC могут использоваться приложением двумя разными способами. Код библиотеки MFC либо непосредственно записывается в выполняемый файл приложения, либо вызывается по мере необходимости из отдельной dll-библиотеки.

Использование для приложения DLL-библиотеки немного ускоряет процесс построения проекта и позволяет создавать выполняемые файлы значительно меньшего размера. Однако сам по себе такой выполняемый файл работать не будет. Для него необходима dll-библиотека. Поэтому, если приложение будет устанавливаться и на других компьютерах, его надо распространять вместе с dll-библиотекой.

Замечание. Если для создания нового приложения используется MFC AppWizard, библиотека MFC подключается автоматически. Программисту не нужно вручную вносить изменения в проектный файл в этом случае.

Рассмотрим, как работает приложение first на уровне исходного текста. Сначала в текст приложения включается файл afxwin.h. В этом файле определены классы, методы, константы и другие структуры для библиотеки классов MFC. Кроме того, включаемый файл afxwin автоматически подключает другой файл - windows.h, необходимый для вызовов функций стандартного программного интерфейса Windows.

Сравним исходный текст приложения first с аналогичным приложением, созданным без использования библиотеки классов MFC. В этом приложении присутствует главная функция приложения WinMain, которая вызывается, когда пользователь или операционная система запускает приложение:

 #include <windows.h>

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

  LPSTR lpCmdLine, int nShowCmd)

{

 // Отображение диалоговой панели.

 MessageBox(NULL,"First MFC-application","Message",MB_OK);

 // Завершение работы приложения

 return 0;

}

Если посмотреть на текст программы first, то там нет хорошо знакомой функции WinMain. Не видно также переменных, представляющих параметры этой функции.

В приложениях, основанных на классах MFC, функция WinMain скрыта от программиста в определении класса CWinApp. В каждом приложении определяется главный класс приложения, наследуемый от базового класса CWinApp. Приложение должно иметь только один объект главного класса приложения, наследованного от класса CWinApp.

Класс CWinApp выполняет все действия, которые обычно выполняет функция WinMain, - инициализирует приложение, обрабатывает сообщения и завершает приложение. Для этого класс CWinApp включает виртуальные методы InitApplication, InitInstance, Run и ExitInstance.

Чтобы выполнить инициализацию приложения, функция WinMain вызывает методы InitApplication и InitInstance для объекта главного класса приложения. Метод InitApplication выполняет инициализацию на уровне приложения. Программист может переопределить этот метод в своем приложении. Метод InitInstance выполняет инициализацию каждой копии приложения. Обычно этот метод создает главное окно приложения. Программист должен обязательно переопределить этот метод в своем приложении. Остальные методы, например Run, можно не переопределять.

Затем функция WinMain начинает обрабатывать цикл сообщений. Для этого вызывается метод Run. Можно переопределить этот метод, чтобы реализовать собственный цикл обработки сообщений.

Когда приложение заканчивает работу и цикл обработки сообщений завершается, вызывается метод ExitInstance. Программист может переопределить этот метод, чтобы выполнить какие-либо действия перед завершением приложения.

В случае приложения first главный класс приложения CFirstApp наследуется от базового класса CWinApp. При этом базовый класс указан как public. Это означает, что в программе доступны все элементы базового класса CWinApp, объявленные как public. Можно вызывать методы класса CWinApp для объектов класса CFirstApp и обращаться к элементам данных класса CWinApp.

В объявлении класса CFirstApp объявлен виртуальный метод InitInstance. Этот метод переопределяется в приложении. Изначально метод InitInstance определен в классе CWinApp. Он отвечает за инициализацию приложения. Он вызывается каждый раз, когда пользователь запускает приложение. Если пользователь запустит приложение несколько раз, то метод InitInstance будет вызываться каждый раз.

Метод InitInstance обязательно должен быть переопределен в главном классе приложения. Остальные виртуальные методы можно оставить без изменения.

Сразу после объявления главного класса приложения создается объект theApp этого класса. Объект главного класса приложения должен быть определен как глобальный. В этом случае он будет создан сразу при запуске приложения и сможет управлять всей работой приложения. После создания глобального объекта вызывается функция WinMain, определенная в классе CWinApp. Она выполняет свои обычные функции - регистрирует классы окон, создает окно и т.д.

Нельзя создавать два или более объекта класса, наследованного от базового класса CWinApp. Каждое приложение должно иметь один и только один объект главного класса приложения.

Метод InitInstance главного класса приложения CFirstApp служит для инициализации. Он вызывается автоматически всякий раз, когда запускается очередная копия приложения. В приложении first метод InitInstance используется для вывода на экран диалоговой панели при помощи функции AfxMessageBox, определенной в MFC.

Вместо функции AfxMessageBox можно воспользоваться функцией MessageBox программного интерфейса Windows. Когда из приложения, созданного с использованием классов MFC, вызываются функции программного интерфейса Windows, необходимо указывать перед именем функции символы ::. Например, вызов функции MessageBox будет выглядеть следующим образом:

::MessageBox(NULL,"First MFC-application","Message",MB_OK);

В конце метода InitInstance вызывается оператор return и возвращается значение FALSE. Приложение сразу же завершается. Если метод InitInsatnce вернет значение TRUE, приложение продолжит свою работу и приступит к обработке очереди сообщений.

Приложение с главным окном

Приложение first не имело главного окна. Для вывода сообщения на экран использовалась функция AfxMessageBox, которая очень похожа на функцию MessageBox программного интерфейса Windows.

Рассмотрим другое приложение- приложение start, оно несколько сложнее предыдущего. При запуске оно отображает на экране компьютера обычное окно, имеющее заголовок, системное меню и кнопки управления.

Точно так же, как и в приложении first, во втором приложении используется класс CWinApp в качестве главного класса приложения. Для управления окном приложения создается еще один класс, наследуемый от базового класса CFrameWnd, входящего в библиотеку MFC.

Файл start.h

#include <afxwin.h>

class CStartApp: public CWinApp

{

 public:

 virtual BOOL InitInstance();

};

Файл startm.h

 #include <afxwin.h>

// Класс CMainWindow - представляет главное окно приложения.

 class CMainWindow : public CFrameWnd

{

public:

 CMainWindow();

};

Файл start.cpp

#include <afxwin.h>

#include "start.h"

#include "startm.h"

BOOL CStartApp::InitInstance()

{

 // Создание объекта класса CMainWindow

 m_pMainWnd= new CMainWindow();

 // Отображение окна на экране.

 // Параметр m_nCmdShow определяет режим отображения окна.

 m_pMainWnd->ShowWindow(m_nCmdShow);

 // Обновление содержимого окна.

 m_pMainWnd->UpdateWindow();

 return TRUE;

}

CStartApp theApp;

Файл startm.cpp

#include <afxwin.h>

#include "startm.h"

// Конструктор класса CMainWindow

CMainWindow::CMainWindow()

 {

 // Создание окна приложения

 Create(NULL,"Hello");

}

Приложение start очень простое - оно состоит из одного главного окна и не содержит ни меню, ни каких-либо других органов управления. И тем не менее главное окно приложения обладает всеми возможностями Windows-окон. Оно имеет заголовок, системное меню и кнопки управления. Можно изменить размер этого окна, увеличить его на весь экран и уменьшить до размера пиктограммы.

В исходных текстах определяется главный класс CStartApp приложения, который наследуется от базового класса CWinApp. При этом базовый класс указан как public. Можно вызывать методы класса CWinApp для объектов класса CStartApp и обращаться к элементам данных класса CWinApp.

В определении класса CStartApp объявлен виртуальный метод InitInstance. Он переопределяется в файле реализации класса. После объявления главного класса приложения и переопределения функции InitInstance Метод InitInstance главного класса приложения CStartApp служит для инициализации. Он вызывается автоматически каждый раз, когда запускается очередная копия приложения.

Второй класс, класс CMainWindow, наследуется от базового класса CFrameWnd как public и представляет главное окно приложения. В классе главного окна определяется только конструктор.

В данном приложении метод InitInstance используется для отображения на экране окна приложения. Для этого создается объект класса CMainWindow и записывается указатель на этот объект в элемент данных m_pMainWnd класса CWinThread (этот класс является базовым для класса CWinApp). Таким образом, объект приложения и объект окна приложения связываются вместе.

Для создания объекта класса CMainWindow используется оператор new. Он создает объект указанного класса, отводит память и возвращает указатель на него. При создании нового объекта класса окна оператором new для автоматически вызывается конструктор.

Само окно появится на экране только после того, как будет вызван метод ShowWindow. В качестве параметра методу ShowWindow передается значение m_nCmdShow. Переменная m_nCmdShow является элементом класса CWinApp. Его назначение соответствует параметру функции WinMain, который определяет, как должно отображаться главное окно приложения сразу после его запуска.

После появления окна на экране ему передается сообщение WM_PAINT при помощи вызова метода UpdateWindow. По этому сообщению приложение должно обновить содержимое окна.

В конце метода InitInstance вызывается оператор return и возвращается значение TRUE, означающее, что инициализация приложения завершилась успешно и можно приступать к обработке очереди сообщений (eсли метод InitInstance вернет значение FALSE, приложение немедленно завершится; эта возможность использовалась в приложении first).

Для создания окна приложения создается объект класса CMainWindow. Такой объект - это не окно, которое пользователь видит на экране компьютера. Этот объект является внутренним представлением окна. Для создания окна предназначается метод Create, определенный в классе CFrameWnd. Он создает окно и связывает его с объектом C++, в случае приложения start - с объектом класса CMainWindow. Метод Create вызывается в конструкторе класса CMainWindow.

Обработка окном сообщений

Работа операционной системы Windows основана на обработке сообщений. Когда пользователь работает с устройствами ввода/вывода (например, клавиатурой или мышью), драйверы этих устройств создают сообщения, описывающие его действия.

Сообщения сначала попадают в системную очередь сообщений операционной системы. Из нее сообщения передаются приложениям, которым они предназначены, и записываются в очередь приложений. Каждое приложение имеет собственную очередь сообщений.

Приложение в цикле, который называется циклом обработки сообщений, получает сообщения из очереди приложения и направляет их соответствующей функции окна, которая и выполняет обработку сообщения. Цикл обработки сообщений в традиционной Windows-программе обычно состоял из оператора while, в котором циклически вызывались функции GetMessage и DispatchMessage. Для более сложных приложений цикл обработки сообщений содержал вызовы других функций (TranslateMessage, TranslateAccelerator). Они обеспечивали предварительную обработку сообщений.

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

Если при создании приложения используется библиотека классов MFC, то за обработку сообщений отвечают классы. Любой класс, наследованный от базового класса CCmdTarget, может обрабатывать сообщения. Чтобы класс смог обрабатывать сообщения, необходимо, чтобы он имел таблицу сообщений класса. В этой таблице для каждого сообщения указан метод класса, предназначенный для его обработки.

Группы сообщений

Сообщения, которые могут обрабатываться приложением, построенным с использованием библиотеки классов MFC, делятся на 3 группы.

Оконные сообщения

Эта группа включает сообщения, предназначенные для обработки функцией окна. Практически все сообщения, идентификаторы которых начинаются префиксом WM_, за исключением WM_COMMAND,. относятся к этой группе.

Оконные сообщения предназначаются для обработки объектами, представляющими окна. Это могут быть практически любые объекты класса CWnd или классов, наследованных от него (CFrameWnd, CMDIFrameWnd, CMDIChildWnd, CView, CDialog). Характерной чертой этих классов является то, что они включают идентификатор окна.

Большинство этих сообщений имеют параметры, детально характеризующие сообщение.

Сообщения от органов управления

Эта группа включает в себя сообщения WM_COMMAND от дочерних окон (включая окна стандартных классов), передаваемых их родительскому окну. Сообщения от органов управления обрабатываются точно таким же образом, что и оконные сообщения.

Исключение составляет сообщение WM_COMMAND с кодом извещения BN_CLICKED. Это сообщение передается кнопкой, когда пользователь на нее нажимает. Обработка сообщений с кодом извещения BN_CLICKED от органов управления происходит аналогично обработке командных сообщений.

Командные сообщения

Это сообщения WM_COMMAND от меню, кнопок панели управления и клавиш акселераторов. В отличие от оконных сообщений и сообщений от органов управления командные сообщения могут быть обработаны более широким спектром объектов. Эти сообщения обрабатывают не только объекты, представляющие окна, но также объекты классов, представляющих приложение, документы или шаблон документов.

Характерной особенностью командных сообщений является идентификатор. Идентификатор командного сообщения определяет объект, который вырабатывает (посылает) данное сообщение.

Таблица сообщений

В библиотеке классов MFC для обработки сообщений используется специальный механизм, который имеет название Message Map - таблица сообщений.

Таблица сообщений состоит из набора специальных макрокоманд, ограниченных макрокомандами BEGIN_MESSAGE_MAP и END_MESSAGE_MAP. Между ними расположены макрокоманды, отвечающие за обработку отдельных сообщений:

BEGIN_MESSAGE_MAP(ИмяКласса,ИмяБазовогоКласса)

 // макросы

END_MESSAGE_MAP()

Макрокоманда BEGIN_MESSAGE_MAP представляет собой заголовок таблицы сообщений. Она имеет два параметра. Первый параметр содержит имя класса таблицы сообщений. Второй - указывает его базовый класс.

Если в таблице сообщений класса отсутствует обработчик для сообщения, оно передается для обработки базовому классу, указанному вторым параметром макрокоманды BEGIN_MESSAGE_MAP. Если таблица сообщений базового класса также не содержит обработчик этого сообщения, оно передается следующему базовому классу и т.д. Если ни один из базовых классов не может обработать сообщение, выполняется обработка по умолчанию, зависящая от типа сообщения:

  •  стандартные сообщения Windows обрабатываются функцией обработки по умолчанию;
  •  командные сообщения передаются по цепочке следующему объекту, который может обработать командное сообщение.

Можно определить таблицу сообщений класса вручную, однако более удобно воспользоваться для этой цели средствами ClassWizard. ClassWizard не только позволяет в удобной форме выбрать сообщения, которые должен обрабатывать класс. Он включит в состав класса соответствующие методы-обработчики. Программисту останется только вставить в них необходимый код. К сожалению, использовать все возможности ClassWizard можно только в том случае, если приложение создано с применением средств автоматизированного программирования MFC AppWizard.

Рассмотрим макрокоманды, отвечающие за обработку различных типов сообщений.

Макрокоманда ON_WM_<name>. Обрабатывает стандартные сообщения операционной системы Windows. Вместо <name> указывается имя сообщения без префикса WM_. Например:

ON_WM_CREATE()

Для обработки сообщений, определенных в таблице макрокомандой On_WM_<name>, вызываются одноименные методы. Имя метода обработчика соответствует названию сообщения, без учета префикса WM_. В классе CWnd определены обработчики для стандартных сообщений. Эти обработчики будут использоваться по умолчанию.

Макрокоманды ON_WM_<name> не имеют параметров. Однако методы, которые вызываются для обработки соответствующих сообщений, имеют параметры, которые, количество и назначение которых зависит от обрабатываемого сообщения.

Если определить обработчик стандартного сообщения Window в своем классе, то он будет вызываться вместо обработчика, определенного в классе CWnd (или другом базовом классе). В любом случае можно вызвать метод-обработчик базового класса из своего метода-обработчика.

Макрокоманда ON_REGISTERED_MESSAGE. Эта макрокоманда обслуживает сообщения операционной системы Windows, зарегистрированные с помощью функции RegisterWindowMessage. Параметра nMessageVariable этой макрокоманды указывает идентификатор сообщения, для которого будет вызываться метод memberFxn:

 ON_REGISTERED_MESSAGE(nMessageVariable, memberFxn)

Макрокоманда ON_MESSAGE. Данная макрокоманда обрабатывает сообщения, определенные пользователем. Идентификатор сообщения (его имя) указывается параметром message. Метод, который вызывается для обработки сообщения, указывается параметром memberFxn:

 ON_MESSAGE(message,memberFxn)

Макрокоманда ON_COMMAND. Эти макрокоманды предназначены для обработки командных сообщений. Командные сообщения поступают от меню, кнопок панели управления и клавиш акселераторов. Характерной особенностью командных сообщений является то, что с ними связан идентификатор сообщения.

Макрокоманда ON_COMMAND имеет два параметра. Первый параметр соответствует идентификатору командного сообщения, а второй - имени метода, предназначенного для обработки этого сообщения. Таблица сообщений должна содержать не больше одной макрокоманды для командного сообщения:

ON_COMMAND(id,memberFxn)

Обычно командные сообщения не имеют обработчиков, используемых по умолчанию. Существует только небольшая группа стандартных командных сообщений, имеющих методы-обработчики, вызываемые по умолчанию. Эти сообщения соответствуют стандартным строкам меню приложение. Так например, если строке Open меню File присвоить идентификатор ID_FILE_OPEN, то для его обработки будет вызван метод OnFileOpen, определенный в классе CWinApp.

Макрокоманда ON_COMMAND_RANGE. Макрокоманда ON_COMMAND ставит в соответствие одному командному сообщению один метод-обработчик В некоторых случаях более удобно, когда один и тот же метод-обработчик применяется для обработки сразу нескольких командных сообщений с различными идентификаторами. Для этого предназначена макрокоманда ON_COMMAND_RANGE.

Она назначает один метод-обработчик для обработки нескольких командных сообщений, интервалы которых лежат в интервале от id1 до id2:

 ON_COMMAND_RANGE(id1,id2,memberFxn)

Макрокоманда ON_UPDATE_COMMAND_UI. Данная макрокоманда обрабатывает сообщения, предназначенные обновления пользовательского интерфейса, например меню, панелей управления, и позволяет менять их состояние.

Параметр id указывает идентификатор сообщения, а параметр memberFxn - имя метода для его обработки:

 ON_UPDATE_COMMAND_UI(id,memberFxn)

Методы, предназначенные для обработки данного класса сообщений, должны быть определены с ключевым словом afx_msg и иметь один параметр - указатель на объект класса CCmdUI. Для удобства имена методов, предназначенных для обновления пользовательского интерфейса, начинаются с OnUpdate:

afx_msg void OnUpdate<имя_обработчика>(CCmdUI* pCmdUI);

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

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

При этом посылается несколько сообщений, по одному для каждой строке меню. С помощью макрокоманд ON_UPDATE_COMMAND_UI можно определить методы-обработчики, ответственные за обновление внешнего вида каждой строки меню и соответствующие ей кнопки на панели управления. Эти методы могут изменять состояние строки меню - отображать ее серым цветом, запрещать ее выбор, отображать около нее символ "галочка" и т.д.

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

Макрокоманда ON_UPDATE_COMMAND_UI_RANGE. Эта макрокоманда обеспечивает обработку сообщений, предназначенных для обновления пользовательского интерфейса, идентификаторы которых лежат в интервале от id1 до id2. Параметр memberFxn указывает метод, используемый для обработки:

ON_UPDATE_COMMAND_UI_RANGE(id1,id2,memberFxn)

Макрокоманда ON_<name>. Данные макрокоманды предназначены для обработки сообщений от органов управления. Такие сообщения могут передаваться органами управления диалоговой панели. Сообщения от органов управления не имеют обработчиков, используемых по умолчанию. При необходимости их нужно определить самостоятельно.

Все макрокоманды ON_<name> имеют два параметра. В первом параметре id указывается идентификатор органа управления. Сообщения от этого органа управления будут обрабатываться методом memberFxn. Например:

 ON_BN_CLICKED(id,memberFxn)

Макрокоманда ON_CONTROL_RANGE. Эта макрокоманда обрабатывает сообщения от органов управления, идентификаторы которых находятся в интервале от id1 до id2. Параметр wNotifyCode содержит код извещения. Метод-обработчик указывается параметром memberFxn:

 ON_CONTROL_RANGE(wNotifyCode,id1,id2,memberFxn)

Приложение, обрабатывающее сообщения

Предыдущие два рассматриваемых приложения, фактически никак не могли взаимодействовать с пользователем. Они не имели ни меню, ни панели управления. И, самое главное, они не содержали обработчиков сообщений.

Рассмотрим теперь приложение, которое имеет меню и содержит обработчики сообщений, передаваемых приложению, когда пользователь открывает меню и выбирает из него строки. Пусть меню приложения состоит из одного пункта Test. Можно выбрать одну из следующих команд - Beep или Exit.

Файл ресурсов, в который включается описание меню, можно построить либо непосредственным созданием нового файла ресурсов, либо при помощи средств AppWizard. В любом случае при создании меню нужно определить название меню или строки меню. Каждый элемент меню должен иметь уникальный идентификатор, однозначно его определяющий:

Файл resource.h

#define IDR_MENU  101

#define ID_TEST_BEEP 40001

#define ID_TEST_EXIT 40002

Файл resource.rc

#include "resource.h"

IDR_MENU MENU DISCARDABLE

BEGIN

 POPUP "Test"

 BEGIN

  MENUITEM "Beep", ID_TEST_BEEP

  MENUITEM SEPARATOR

  MENUITEM "Exit", ID_TEST_EXIT

 END

END

Файлы, в которых находятся определение классов приложения и главного окна, представлены ниже:

Файл menu.h

#include <afxwin.h>

class CMenuApp: public CWinApp

{

public:

 virtual BOOL InitInstance();

};

Файл menu.cpp

#include <afxwin.h>

#include "menu.h"

#include "menum.h"

BOOL CMenuApp::InitInstance()

{

 m_pMainWnd= new CMainWindow();

 m_pMainWnd->ShowWindow(m_nCmdShow);

 m_pMainWnd->UpdateWindow();

 return TRUE;

}

CMenuApp theApp;

Файл menum.h

#include <afxwin.h>

class CMainWindow : public CFrameWnd

{

public:

 CMainWindow();

 afx_msg void TestBeep();

 afx_msg void TestExit();

 // макрокоманда необходима, так как класс обрабатывает сообщения

 DECLARE_MESSAGE_MAP()

};

Файл menum.cpp

#include <afxwin.h>

#include "menum.h"

 #include "resource.h"

// Таблица сообщений класса

 BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd)

 ON_COMMAND(ID_TEST_BEEP,TestBeep)

 ON_COMMAND(ID_TEST_EXIT,TestExit)

 END_MESSAGE_MAP()

 CMainWindow::CMainWindow()

{

 Create(NULL,"Hello",WS_OVERLAPPEDWINDOW,rectDefault,

  NULL,MAKEINTRESOURCE(IDR_MENU));

}

void CMainWindow::TestBeep()// Метод TestBeep - обрабатывает команду меню

{

 MessageBeep(0);

}

void CMainWindow::TestExit()// Метод TestExit - обрабатывает команду меню

{

 DestroyWindow();

}

Чтобы объекты класса могли обрабатывать сообщения, в определении класса необходимо поместить макрокоманду DECLARE_MESSAGE_MAP. По принятым соглашениям эта макрокоманда должна записываться в секцию public.

Кроме этого, необходимо также определить таблицу сообщений. Таблица начинается макрокомандой BEGIN_MESSAGE_MAP и заканчивается макрокомандой END_MESSAGE_MAP. Между этими макрокомандами расположены строки таблицы сообщений, определяющие сообщения, подлежащие обработке данным классом, и методы, которые выполняют такую обработку.

Приложение может содержать несколько классов, обладающих собственными таблицами сообщений. Чтобы однозначно определить класс, к которому относится таблица сообщений, имя этого класса записывается в первый параметр макрокоманды BEGIN_MESSAGE_MAP.

Приложение menu обрабатывает только две команды от меню приложения. Для обработки этих команд используют методы, представленные в определении класса CMainFrame.

Приложению может поступать гораздо больше сообщений и команд, чем указано в таблице сообщений класса CMainFrame. Необработанные сообщения передаются для обработки базовому классу - классу CFrameWnd. Класс, который будет обрабатывать сообщения, не указанные в таблице сообщений, указывается во втором параметре макрокоманды BEGIN_MESSAGE_MAP.

Замечание. Если класс приложения тоже обрабатывает сообщения (т.е. имеет таблицу сообщений), и некоторые из сообщений обрабатываются как окном, так и приложением, то нужно понять, какова очередность обработки сообщений тем или иным объектом. Те команды, которые не имеют обработчика в таблице сообщений класса окна, передаются для обработки в класс приложения. Если же команда может быть обработана и в классе окна, и в классе приложения, она обрабатывается только один раз в классе окна. Обработчик класса приложения в этом случае не вызывается.

PAGE  17


 

А также другие работы, которые могут Вас заинтересовать

13227. ПЛАНКТОН. Занурення планктонних організмів 1.15 MB
  ЛАБОРАТОРНА РОБОТА № 4 ПЛАНКТОН Мета: Ознайомитись з організмами планктону та з органами руху планктонних організмів з їх пристосуваннями у воді в завислому стані. Закріпити знання студентів із зоології безхребетних про морфологічні особливості будови представ...
13228. Ознайомитися з організмами бентосу 991 KB
  ЛАБОРАТОРНА РОБОТА № 5 БЕНТОС Мета: Ознайомитися з організмами бентосу; закріпити здобуті знання із зоології безхребетних про морфологічні особливості будови та екології поширення представників бентосних організмів. Контрольні запитання Які організм
13229. НЕЙСТОН І ПЕРИФІТОН 521 KB
  ЛАБОРАТОРНА РОБОТА № 6 НЕЙСТОН І ПЕРИФІТОН Мета: Ознайомитись з особливостями будови та способом життя організмів нейстону і перифітону. Контрольні запитання Дати визначення поняття нейстон. Які умови необхідні для розвитку нейстону Які є два ви...
13230. МЕТОДИКА ПРОЕКТУВАННЯ ПРОСТИХ РЕЛЯЦІЙНИХ БАЗ ДАНИХ 1018 KB
  МЕТОДИКА ПРОЕКТУВАННЯ ПРОСТИХ РЕЛЯЦІЙНИХ БАЗ ДАНИХ За матеріалами книги Glenn A. Jackson Relational Database Design With Microcomputer Applications У 1965 р. зявилися перші результати в області управління базами даних роботи Чарльза Бахмана. З тієї пори технології баз даних пройшли ве
13231. Учбово-відлагоджувальний стенд EV8031/AVR (V3.2) 1.13 MB
  Учбово-відлагоджувальний стенд EV8031/AVR V3.2 Методичні вказівки до виконання лабораторних робіт №№ 6–10 ВСТУП Стенд є мікропроцесорним контроллером оснащеним памяттю програм памяттю даних і різноманітними периферійними пристроями. Він д...
13232. Теоретичні основи теплотехніки, Термодинаміка, теплопередача і ТСУ, Енергетичні установки 2.88 MB
  Козак Ф.В. Гаєва Л.І. Негрич В.В. Войцехівська Т.Й. Дем’янчук Я.М. Лабораторний практикум з дисциплін Теоретичні основи теплотехніки Термодинаміка теплопередача і ТСУ Енергетичні установки Наведені загальні положення організації проведення лаборато
13233. Вивчення стенду, команд однокристальної ЕОМ КР1816ВЕ31 27.5 KB
  Лабораторна робота №1. Вивчення стенду команд однокристальної ЕОМ КР1816ВЕ31 Тема: Вивчення стенду команд однокристальної ЕОМ КР1816ВЕ31. Мета роботи: Вивчення функціональних можливостей учбовоналагоджувального стенду внутрішньої структури і системи команд ЕОМ КР1816ВЕ3...
13234. Напівпровідникові діоди 279.5 KB
  Лабораторна робота №1 Тема: Напівпровідникові діоди Мета: 1. Дослідження напруги та струму діода при прямому та оберненому зміщенні рп переходу. Побудова та дослідження вольтамперної характеристики ВАХ для напівпровідникового діода. Дослідження опо
13235. Загальна характеристика друкарського устаткування та класифікація друкарських машин. Технологічні особливості високого та офсетного плоского способів друку 107.5 KB
  ЛАБОРАТОРНА РОБОТА № 1 На тему: Загальна характеристика друкарського устаткування та класифікація друкарських машин. Технологічні особливості високого та офсетного плоского способів друку Мета: Ознайомитись із загальною характеристикою друкарського устат...