Основы программирования с помощью библиотеки microsoft foundation classes


MFC, С чего начать?

17.09.2008, 00:52

С чего начинать изучение MFC?
Здравствуйте немогли бы мне посоветовать хорошую книгу или способ как разобраться с MFC и с чего.

С чего начать?
Хочу изучать visual studio, имею некоторые знания по C++ , подскажите с чего лучше начинать и какую.

с чего начать
вот решил освоить программирование VS++. поставил версию 2010. С чего начать? есть ли какие нибудь.

С чего начать
Добрый день, подскажите пожалуйста, хочу написать на с++ программу не консольную, в студии выбрал.

Подскадите с чего начать
Надо написать программу для контроля температуры и влажности воздуха. Есть контроллер на нем.

17.09.2008, 09:27 2 17.09.2008, 10:29 [ТС] 3 17.09.2008, 11:31 4
17.09.2008, 11:31
21.09.2008, 17:43 5
26.12.2008, 17:33 6

———————Configuration: Step1 — Win32 Debug———————
Compiling.
Step1.cpp
Linking.
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
libcd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/Step1.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

Step1.exe — 4 error(s), 0 warning(s)

пробывал подключать «afxcwd.h» по аналогии с MFC — пишет — C:\Program Files\Microsoft Visual Studio\MyProjects\Step1\Step1.cpp(8) : fatal error C1083: Cannot open include file: ‘nafxcwd.lib’: No such file or directory
Error executing cl.exe.

Подскажите пожалуйста, где может быть ошибка.
Может какой-то файл не подключил.

Добавлено через 16 часов 12 минут 10 секунд
Все. разобрался.
причина такой ошибки в том, что при создании проекта я по привычке выбирал — Win32 Console Application, а нужно было выбирать — Win32 Application.

26.12.2008, 19:23 7
08.02.2009, 18:26 8

Название: MFC — Внутренний мир
Автор: Румянцев П.В.
Издательство: Москва Горячая линия — Телеком
Год: 2003
Страниц: 350
Формат: DJVU
Размер: 3.5 Mb
ISBN: 5-93517-113-9
Качество: Хорошее
Язык: Русский
Книга содержит информацию о библиотеке классов MFC (Microsoft Foundation Classes) и методах создания Windows-приложений на основе классов этой библиотеки. Сведения, изложенные в этой книге, собраны автором исключительно на основе изучения и анализа исходных кодов MFC.
Для программистов.

Содержание:
Предисловие. ПОЧЕМУ Я РЕШИЛ НАПИСАТЬ ЭТУ КНИГУ
Часть I. ПЕРВАЯ ПРОГРАММА НА MFC
Часть II. ВОЗМОЖНОСТИ MFC, НЕ СВЯЗАННЫЕ С ОКОННЫМ ИНТЕРФЕЙСОМ
Часть III. АРХИТЕКТУРА «ДОКУМЕНТ/ПРЕДСТАВЛЕНИЕ» (DOCUMENT/VIEW)
Приложение А. Нотификационные сообщения
Приложение Б. Сигнатуры
Приложение В. Макросы и их определения

Основные понятия MFC MFC Concepts

В этом разделе содержатся общие сведения и разделы на основе задач, которые помогут программировать работу с библиотекой Microsoft Foundation Class (MFC). This section provides conceptual and task-based topics to help you program using the Microsoft Foundation Class (MFC) Library.

В этом разделе In This Section

Общие разделы по MFC General MFC Topics
Описание технических деталей библиотеки MFC. Discusses the technical details of the MFC Library.

Использование CObject Using CObject
Предоставляет ссылки на использование CObject базового класса для большинства классов в MFC. Provides links to using CObject , the base class for most classes in MFC.

Коллекции Collections
Обсуждаются классы коллекций, созданные из C++ шаблонов и не созданные. Discusses collection classes created from and not created from C++ templates.

Дата и время Date and Time
Содержит ссылки на разделы, посвященные использованию MFC в качестве даты и времени. Provides links to topics discussing using date and time with MFC.

Файлы Files
CFile Описание и способы управления файлами в MFC. Discusses CFile and how to handle files in MFC.

Управление памятью (MFC) Memory Management (MFC)
Описывает, как использовать преимущества служб общего назначения, связанных с управлением памятью. Describes how to take advantage of the general-purpose services related to memory management.

Обработка и сопоставление сообщений Message Handling and Mapping
Описывает процесс обработки сообщений и команд платформой MFC и способ их подключения к их функциям обработчика. Describes how messages and commands are processed by the MFC framework and how to connect them to their handler functions.

Сериализация Serialization
Описание механизма сериализации, обеспечивающего сохранение объектов между запусками программы. Explains the serialization mechanism provided to allow objects to persist between runs of your program.

Обработка исключений (MFC) Exception Handling (MFC)
Описывает механизмы обработки исключений, доступные в MFC. Explains the exception-handling mechanisms available in MFC.

Основы программирования для интернет-решений MFC MFC Internet Programming Basics
Обсуждаются классы MFC, поддерживающие Интернет. Discusses the MFC classes that support Internet programming.

Задачи программирования для интернет-решений MFC MFC Internet Programming Tasks
Описывает, как добавить в приложения поддержку Интернета. Discusses how to add Internet support to your applications.

Поддержка Юникода и многобайтовой кодировки Unicode and Multibyte Character Set (MBCS) Support
Объясняет, как использовать MFC и поддержку ATL для кодировки Юникод и многобайтовых кодировок. Explains how to use MFC and ATL support for Unicode and multibyte character sets.

MFC COM MFC COM
Описывает подмножество MFC, предназначенное для поддержки модели COM, в то время как большая часть библиотеки шаблонов ATL предназначена для программирования COM. Discusses a subset of MFC, which is designed to support COM, while most of the Active Template Library (ATL) is designed for COM programming.

Реализация многопоточности на языке C++ с помощью классов MFC Multithreading with C++ and MFC
Описывает, какие процессы и потоки являются и обсуждают подход MFC к многопоточности. Describes what processes and threads are and discusses the MFC approach to multithreading.

Сокеты Windows в MFC Windows Sockets in MFC
Охватывает реализацию MFC сокетов Windows. Covers the MFC implementation of Windows Sockets.

Справочник по MFC MFC Reference
Предоставляет справочные материалы по библиотеке MFC, а также набор классов, образующих исполняющую среду, т.е. платформу приложения, написанного для интерфейса Windows API. Provides reference material for the MFC Library, a set of classes that constitute an application framework, which is the framework of an application written for the Windows API.

Примеры MFC MFC Samples
Содержит ссылки на примеры, демонстрирующие использование MFC в классических приложениях, библиотеках DLL, приложениях баз данных, элементах управления, веб-приложениях и многом другим. Provides links to samples that show how to use MFC in desktop applications, DLLs, database applications, controls, Web applications, and more.

Библиотека классов MFC

Microsoft Foundation > Примеры программ для лекции.

MFC – это библиотека классов, написанных на языке C++. MFC является оболочкой для Win32 API и содержит многоуровневую иерархию классов. Не все функции Win32 API включены в MFC . С другой стороны, эта библиотека классов охватывает большую часть функциональных возможностей Windows , и предоставляет разработчику ряд дополнительных механизмов для проектирования и создания программных продуктов.

На вершине иерархии MFC находится единственный базовый класс – CObject. Все остальные классы библиотеки MFC можно условно разбить на две группы: производные и не производные от него. Чаще всего, создание нового MFC -приложения поручается мастеру MFC Application Wizard . Мастер генерирует основной скелет приложения, который впоследствии заполняется нужным кодом, давая готовое приложение .

Основные классы MFC

Некоторые классы MFC порождаются непосредственно от CObject . Наиболее широко используемыми среди них являются CCmdTarget, CFile, CDC , CGDIObject и CMenu . Класс CCmdTarget предназначен для обработки сообщений. Класс CFile предназначен для работы с файлами. Класс CDC обеспечивает поддержку контекстов устройств. В этот класс включены практически все функции графики GDI. CGDIObject является базовым классом для различных GDI-объектов, таких как перья, кисти, шрифты и другие. Класс СMenu предназначен для работы меню.

От класса CCmdTarget порождается очень важный класс CWnd . Он является базовым для создания всех типов окон, включая масштабируемые («обычные») и диалоговые, а также различные элементы управления. Наиболее широко используемым производным классом является CFrameWnd . В большинстве программ главное окно создается с помощью именно этого класса. От класса CCmdTarget , через класс CWinThread , порождается единственный из наиболее важных классов, обращение к которому в MFC-программах происходит напрямую, это класс CWinApp . Это один из фундаментальных классов, поскольку предназначен для создания самого приложения. В каждой программе имеется один и только один объект этого класса. Как только он будет создан, приложение начнет выполняться.

Класс CWinApp является базовым классом, на основе которого образуют обязательный объект – приложение Windows. Основными задачами объекта этого класса являются инициализация и создание главного окна, а затем опрос системных сообщений. Иерархия класса CWinApp : CObject -> CCmdTarget -> CWinThread -> CWinApp

Класс CFrameWnd («окна-рамки») и производные от него классы определяют окна-рамки на мониторе. Элементы управления, создаваемые при проектировании интерфейса пользователя, принадлежат семейству классов элементов управления. Появляющиеся в процессе работы приложения диалоговые окна – это объекты классов, производных от CDialog . Классы CView, CFrameWnd, CDialog и все классы элементов управления наследуют свойства и поведение своего базового класса CWnd («окно»), определяющего, по существу, Windows-окно. Этот класс, в свою очередь, является наследником базового класса CObject («объект»). Как правило, структура приложения определяется архитектурой Document-View (документ-вид). Это означает, что приложение состоит из одного или нескольких документов – объектов, классы которых являются производными от класса CDocument (класс «документ»). С каждым из документов связаны один или несколько видов – объектов классов, производных от CView (класс «вид» ), и определяющих методы обработки объектов класса документа.

Соглашение об именах MFC

В качестве префикса, обозначающего имя класса, библиотека MFC использует заглавную букву «C» (от слова «class»), за которой идет имя, характеризующее назначение класса. Например:

  • CWinApp – класс, определяющий приложение;
  • CWnd – базовый класс для всех оконных объектов;
  • CDialog – класс диалога.

При определении имен функций-членов классов используется три варианта:

  1. Имя объединяет глагол и существительное – DrawText (нарисовать текст).
  2. Имя состоит только из существительного – DialogBox (блок диалога).
  3. Для функций, предназначенных для преобразования одного типа в другой, используются такие имена, как XtoY (из X в Y).

Для членов классов библиотеки MFC используется следующий способ назначения имен: обязательный префикс m_ (от class member – член класса), за которым идет префикс, характеризующий тип данных, и завершается все заданием содержательного имени переменной. Например, m_pMainWnd – указатель на класс главного окна. Для переменных, которые не являются членами класса, m_ не ставится.

Включаемые файлы

AFXWIN.H – содержит описание основных классов библиотеки и сводит воедино все включаемые файлы, необходимые для работы MFC.

AFX.H – содержит описания классов общего назначения, макросы, базовые типы данных MFC.

AFXRES.H – подключает стандартные идентификаторы ресурсов.

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

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

Карта сообщений

Для создания стандартного окна в приложении должен наследоваться класс от CFrameWnd . Он содержит конструктор и макрос DECLARE_MESSAGE_MAP() . Макрос декларирует карту сообщений, которая определяет, какая член-функция класса должна вызываться в ответ на сообщение Windows. Этот макрос применяется для любого окна, в котором обрабатываются сообщения. Он должен быть последним в декларировании класса, использующего карту сообщений. В конце программы помещается реализация карты сообщений:

BEGIN_MESSAGE_MAP(CMainWnd /*класс окна*/, CFrameWnd /* класс-предок */) END_MESSAGE_MAP()

Первый макрос всегда имеет два параметра, первый – класс окна, второй – класс, от которого порожден класс окна. В данном примере карта сообщений пустая, то есть все сообщения обрабатывает MFC.

В библиотеке MFC все возможные сообщения разделены на три основные категории:

  1. сообщения Windows;
  2. извещения элементов управления;
  3. командные сообщения (команды).

В первую категорию входят сообщения, имена которых начинаются с префикса WM_ , за исключением WM_COMMAND . Во вторую категорию входят извещения ( notification messages ) от элементов управления и дочерних окон, направляемых родительским окнам. Третья категория охватывает все сообщения WM_COMMAND , называемых командами (командными сообщениями), от объектов интерфейса пользователя, который включает меню, кнопки панелей инструментов и акселераторы.

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

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

Включение макрокоманд в карту сообщений

Чтобы программа могла ответить на сообщение, в карту сообщений должна быть включена соответствующая макрокоманда. Названия макрокоманд соответствуют именам стандартных сообщений Windows, но дополнительно имеют префикс ON_ и заканчиваются парой круглых скобок. Из этого правила есть исключение: сообщению WM_COMMAND соответствует макрокоманда ON_COMMAND(. ) . Причина в том, что это сообщение обрабатывается особым образом. Чтобы включить макрокоманду в очередь сообщений, необходимо поместить ее между командами BEGIN_MESSAGE_MAP(…) и END_MESSAGE_MAP() . Например, если необходимо обработать в программе сообщение WM_CHAR , то очередь должна выглядеть так:

В очереди может находиться более одной макрокоманды. Сообщение WM_CHAR генерируется при нажатии алфавитно-цифровой клавиши на клавиатуре.

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

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

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

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

Сообщение WM_PAINT

Операционная система Windows устроена таким образом, что за обновление содержимого окна отвечает программа. Например, если часть окна была перекрыта другим окном, а затем вновь открыта, или минимизированное окно было восстановлено, то окну посылается сообщение WM_PAINT . В ответ на него окно должно обновить свою клиентскую область. Прототип обработчика WM_PAINT следующий:

afx_msg void OnPaint();

Макрокоманда называется ON_WM_PAINT() .

Для примера создадим обработчик, который выводит строку «Использование OnPaint()» в клиентскую область по координатам x = 25, y = 25:

В обработчике WM_PAINT нужно всегда пользоваться классом CPaintDC , который представляет собой класс клиентской области, но предназначенный для использования именно с этим сообщением. Это обусловлено архитектурой самой Windows. Функция TextOut(…) предназначена для вывода текста в контекст устройства (в данном случае – в окно). При ее использовании, по умолчанию первые два параметра определяют координаты верхнего левого угла текстовой строки. По умолчанию координаты представляют собой реальные пиксели, ось x направлена слева направо, ось y – сверху вниз. Эта функция перегруженная, наиболее удобный для нас вариант – когда третий параметр имеет тип CString . Этот класс входит в MFC и является очень удобной заменой для строк, завершаемых нулем. Большинство реальных окон (за исключением диалогов) должны обрабатывать сообщение WM_PAINT . Более того, если Вы хотите написать корректную программу, то весь вывод в окно должен осуществляться только в обработчике WM_PAINT . В случае получения контекста из обработчика WM_PAINT с помощью класса CPaintDC , Windows гарантирует наличие свободного контекста.

Введение в Visual C++. MFC

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

Вероятно, что лучшей интегрированной средой разработки приложений под Windows, является Microsoft Visual C++. Именно этой программой мы и будем пользоваться в дальнейшим. Установочный образ Вы можете скачать на сайте разработчика , впрочем, думаю у вас не возникнет проблем с этой фундаментальной задачей.

Компания Microsoft разработала мощный инструмент для разработки сложных приложений — MFC. MFC (Microsoft Foundation Classes) — библиотека классов языка C++, предназначенная для создания визуальных приложений при помощи встроенных средств. MFC поддерживает современные технологии программирования, благодаря чему программы написанные с ее помощью будут обладать необходимой функциональностью и надежностью. Благодаря ей программист получает шаблонный «скелет» программы, после чего ему остается вписать код в необходимые места.

Итак, теперь стоит поговорить о более грустных вещах. Библиотека MFC достаточно сложна, так как во всю использует возможности языка C++. А это значит, что в «арсенале» начинающего изучать визуальное программирование используя этот «дар» от Microsoft должны присутствовать навыки написания кода на C++. В частности было бы неплохо изучить: рекурсию и перегрузку функций, основы классов, перегрузку операций и наследование. Но для самых отчаянных (тех кто не боится не разобраться что к чему), думаю возможно дуализировать задачи, то есть одновременно изучать как библиотеку MFC, так и базовые понятия C++.

Что касается самой Visual C++, то тут стоит добавить, что эта среда разработки обычно входит в линейку программ под общим названием Visual Studio, но вполне реально приобрести ее в отдельном экземпляре.

Основы программирования с помощью библиотеки microsoft foundation classes

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

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

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

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

Класс Массив содержит
CByteArray Байты
CDWordArray Двойные слова
CObArray Указателей на объекты класса CObject
CPtrArray Указателей типа void
CStringArray Объекты класса CString
CUIntArray Элементы класса unsigned integer или UINT
CWordArray Слова

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

Для построения массивов вы можете также воспользоваться шаблоном CTypedPtrArray. Этот шаблон не наследуется от базового класса CObject, поэтому использовать методы класса CObject для него нельзя.

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

Класс Список содержит элементы
CObList Указатели на объекты класса CObject
CPtrList Указатели типа void
CStringList Объекты класса CString

Перечисленные в таблице классы позволяют построить списки из элементов любых типов и объектов любых классов. Однако удобнее пользоваться шаблоном CList, также наследованным от базового класса CObject. Для построения списков вы можете также использовать шаблон CTypedPtrList. Этот шаблон не наследуется от базового класса CObject.

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

Класс Ключевое поле Поле, связанное с ключевым
CMapPtrToPtr Указатель типа void Указатель типа void
CMapPtrToWord Указатель типа void Слово
CMapStringToOb Объекты класса CString Указатели на объекты класса CObject
CMapStringToPtr Объекты класса CString Указатель типа void
CMapStringToString Объекты класса CString Объекты класса CString
CMapWordToOb Слово Указатели на объекты класса CObject
CMapWordToPtr Слово Указатель типа void

Вы можете создавать словари, имеющие поля любых типов и классов, если воспользуетесь шаблоном CMap. Шаблон CMap наследуется от базового класса CObject. Для построения словарей можно также использовать шаблон CTypedPtrMap. Шаблон CTypedPtrMap не наследуется от базового класса CObject.

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

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

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

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

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

Рис. 2.6. Класс CDC

В следующей таблице приведено краткое описание классов, наследованных от CDC.

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

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

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

Рис. 2.7. Класс CGdiObject

Класс Описание
CBitmap Растровое изображение bitmap
CBrush Кисть
CFont Шрифт
CPalette Палитра цветов
CPen Перо
CRgn Область внутри окна

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

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

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

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

Базы данных (классы для работы с базами данных)

В MFC включены несколько классов, обеспечивающую поддержку приложений, работающих с базами данных. В первую очередь это классы ориентированные на работу с ODBC драйверами – CDatabase и CRecordSet. Поддерживаются также новые средства для работы с базами данных DAO (Data Access Object). Для этого предназначены классы CDaoDatabase, CDaoRecordSet, CDaoQueryDef, CDaoTableDef, CDaoWorkspace и CLongBinary.

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

Классы CFieldExchange и CDaoFieldExchange работают с процедурами обмена данными RFX (Record Field Exchange ) для классов управляющих базами данных.

Синхронизация задач приложения (класс CSyncObject)

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

Рис. 2.8. Класс CSyncObject

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

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

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

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

Сокеты (классы CAsyncSocket и CSocket)

Для тех, кто занимается сетевыми коммуникациями, в состав библиотеки MFC включены классы CAsyncSocket и наследованный от него класс CSocket (рис. 2.9). В класс CAsyncSocket включен программный интерфейс Windows Socket.

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

Программирование на уровне программного интерфейса Windows с использованием сокетов описано в двадцать третьем томе серии “Библиотека системного программиста”, который называется “Глобальные сети компьютеров”.

Рис. 2.9. Класс CAsyncSocket

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

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

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

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

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

Архивный класс (класс CArchive)

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

Более подробно о процессе сохранения и восстановления объектов вы можете прочитать в разделе “Сохранение и восстановление объектов”. Пример использования класса CArchive для записи и восстановления документов в файлах представлен в разделе “Простейший графический редактор” главы “Однооконный интерфейс”.

Информация о классе объекта (структура CRuntimeClass)

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

Отладка приложения (классы CDumpContext, CMemoryState)

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

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

Печать документа (класс CPrintInfo)

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

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

Первое приложение MFC

Первое приложение MFHello, которое мы создадим с использованием библиотеки классов MFC будет очень простое. Единственное, что оно будет делать – это отображать на экране маленькую диалоговую панель, содержащую строку “Hello, MFC!”.

Исходный текст приложения, представленный в листинге 2.1, состоит всего из двенадцати строк, не считая строк комментариев. В нашем первом приложении мы использовали единственный класс библиотеки MFC, наследованный от базового класса CWinApp.

Чтобы создать новый проект, выберите из меню File строку New. На экране появится диалоговая панель New, содержащая одноименный список New и две кнопки. Выберите из списка New строку Project Workspace. Откроется диалоговая панель New project workspace (рис. 4.1 из главы “Приложение с главной диалоговой панелью”). В ней вы должны указать тип приложения, который будет разрабатываться, имя проекта и расположение каталога для записи в него файлов проекта.

Самые простые приложения с использованием библиотеки классов MFC мы будем создавать без использования автоматизированных средств разработки приложений MFC AppWizard. Поэтому в качестве типа приложения выберите из списка Type строку Application.

В поле Name введите имя нового проекта. Наш первый проект мы назвали именем MFHello. Расположение каталога для размещения файлов проекта отображается в поле Location. По умолчанию каталог проекта называется точно также как сам проект и будет размещен в каталоге Projects среды разработки Visual C++. Вы можете выбрать для проекта любой другой каталог, если нажмете на кнопку Browse.

Теперь нажмите кнопку Create. Будут созданы служебные файлы проекта. Они получат названия MFHello.mak, MFHello.ncb и MFHello.mdp. Файл MFHello.mdp является основным файлом проекта. В этих файлах определяется, какие исходные файлы содержит проект, указываются характеристики создаваемого приложения, конфигурация самой среды разработки Visual C++.

Окно Project Workspace

Microsoft Visual C++ версии 4.0 имеет удобные средства для просмотра исходных текстов файлов проекта, кодов классов приложения, ресурсов, а также для получения справочной информации.

Откройте окно Project Workspace. Обычно оно расположено в левой части экрана, но вы можете переместить его в другое место и даже закрыть. Если окно закрыто, откройте его. Для этого выберите из меню View строку Project Workspace. Окно Project Workspace состоит из нескольких страниц. Вы можете открыть их, нажимая на соответствующие закладки. Количество страниц зависит от того, установлена ли справочная система и открыт ли проект.

ClassView. Средство для просмотра и редактирования классов приложения

ResourceView. Позволяет просматривать и редактировать ресурсы приложения

FileView. Выполняет просмотр файлов приложения

InfoView. Справочная система Microsoft Visual C++. В нее включена информация о языке Си, Си++, библиотеки классов MFC, функций програмного интерфейса Windows

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

Чтобы создать новый файл, вы можете нажать кнопку New Source File( ) в стандартной панели управления или выбрать из меню File строку New, а затем из списка в открывшейся панели New выбрать строку Text File. Откроется новое окно текстового редактора. В нем надо набрать исходный текст приложения, представленного листингом 2.1. Сохраните набранный текст в файле под именем MFHello.cpp в каталоге проекта. Для этого выберите из меню File строку Save As.

Листинг 2.1. Файл MFHello.cpp

// Включаемый файл для MFC

// Наследуем от базового класса CWinApp главный

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

class CMFHelloApp : public CWinApp <

// Мы будем переопределять метод InitInstance,

// предназначенный для инициализации приложения

virtual BOOL InitInstance();

// Создаем объект приложение класса CMFHelloApp

// Метод InitInstance класса CMFHelloApp

// Переопределяем виртуальный метод InitInstance

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

Единственный файл с исходным текстом приложения создан и его надо включить в проект. Выберите из меню Insert строку Files into Project. На экране появится диалоговая панель Insert Files into Project. Выберите файл MFHello.cpp и нажмите кнопку Add. Диалоговая панель закроется. Просмотрите еще раз папку с файлами проекта. Теперь в ней расположен файл MFHello.cpp (рис. 2.10).

Рис. 2.10. Файлы проекта MFHello

Откройте страницу ClassView в окне Project Workspace. В ней отображаются все классы, определенные в приложении и все глобальные переменные. Для каждого класса приложения можно видеть входящие в него элементы (рис. 2.11).

На странице ClassView отображается древовидная структура классов вашего приложения. Когда вы в первый раз открываете ClassView, структура классов отображается в виде закрытой папки . Чтобы ее открыть, щелкните два раза левой кнопкой мыши по изображению папки или один раз по символу , расположенному левее папки. В открытой папке символом представлены классы приложения и еще одним символом папки глобальные объекты приложения. Папку с глобальными объектами можно открыть также как папку с классами. Вы можете открыть и сами классы. Так вы сможете просмотреть элементы класса – методы и данные. Методы обозначаются символом , а данные символом . Если методы или данные объявлены как protected, перед ними отображается символ , а если как private – символ .

В нашем проекте определен только один класс CMFHelloApp. В класс CMFHelloApp входит метод InitInstance. Кроме того, определена одна глобальная переменная MFHelloApp.

Рис. 2.11. Классы проекта MFHello

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

Откройте страницу General. Мы привели внешний вид этой страницы на рисунке 2.12. Обратите внимание на список Microsoft Foundation Classes. По умолчанию из этого списка выбрана строка No Using MFC. Она означает, что приложение не будет использовать библиотеку MFC. Так как в приложении MFHello и всех остальных приложениях, описанных в этой книге, задействованы классы MFC, выберите из списка Microsoft Foundation Classes строку Use MFC in a Shared Dll (mfc40(d).dll) или строку Use MFC in a Static Library.

Что же выбрать – Use MFC in a Shared Dll или Use MFC in a Static Library? Оказывается программные коды библиотеки классов MFC могут использоваться приложением двумя способами. Код библиотеки MFC либо непосредственно записывается в выполнимый файл приложения, либо вызывается по мере необходимости из отдельной dll-библиотеки.

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

Для MFC версии 4.0 dll-библиотека хранится в файлах Mfc40d.dll и Mfc40.dll. В файле Mfc40d.dll находится отладочная версия MFC, а в файле Mfc40.dll отладочная информация отсутствует. В ходе установки Visual C++ эти dll-библиотеки записываются в системный каталог операционной системы.

Если вы забудете указать, что приложение использует MFC, то во время построения проекта на этапе установления связи (Linking…) будут обнаружены ошибки:

error LNK2001: unresolved external symbol __endthreadex

error LNK2001: unresolved external symbol __beginthreadex

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

Рис. 2.12. Диалоговая панель Project Settings

Если вы все сделали, постройте проект. Для этого вы можете выбрать из меню Build строку Build MFHello.exe – создать выполнимый файл MFHello.exe или строку Rebuild All – заново оттранслировать все исходные файлы проекта. Если в ходе построения выполнимого файла приложения нашего проекта возникли ошибки, исправьте их и заново оттранслируйте проект. После успешного построения проекта запустите полученное приложение, выбрав из меню Build строку Execute MFHello.exe.

На экране появится маленькая диалоговая панель (рис. 2.13). Название этой диалоговой панели соответствует названию выполнимого файла приложения MFHELLO. В диалоговой панели отображается текстовое сообщение “Hello, MFC!”, пиктограмма с восклицательным знаком внутри треугольника и кнопка OK. Как только вы нажмете кнопку OK, диалоговая панель закрывается и приложение завершит свою работу.

Рис. 2.13. Приложение MFHello

Посмотрим, как работает приложение MFHello на уровне исходного текста. Первая строка, не считая строки комментария, содержит директиву препроцессора #include, которая включает файл afxwin.h :

// Включаемый файл для MFC

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

В предыдущих томах серии “Библиотека системного программиста”, посвященных программированию в среде операционных систем Windows и Windows 95, мы рассказывали о функции WinMain , которая является главной функцией приложения. Эта функция вызывается, когда пользователь или операционная система запускает приложение. Все приложения, которые мы рассматривали до сих пор содержали функцию WinMain:

// Самое простое приложение Windows

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) <

// Отображаем на экране небольшую панель с сообщением

MessageBox(NULL,»Hello, world», «Text Message», MB_OK);

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

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

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

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

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

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

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

// Наследуем от базового класса CWinApp главный

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

class CMFHelloApp : public CWinApp <

// Мы будем переопределять метод InitInstance,

// предназначенный для инициализации приложения

virtual BOOL InitInstance();

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

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

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

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

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

// Создаем объект приложение класса CMFHelloApp

Метод InitInstance главного класса приложения CMFHelloApp служит для инициализации. Он вызывается автоматически каждый раз, когда запускается очередная копия приложения. Мы используем метод InitInstance чтобы вывести на экран компьютера диалоговую панель с сообщением “Hello, MFC!”. Для этого вызываем функцию AfxMessageBox:

// Метод InitInstance класса CMFHelloApp

// Переопределяем виртуальный метод InitInstance

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

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

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

::MessageBox(NULL,»Hello, world!», «Message», MB_OK);

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

Конечно, вы можете продолжать набирать исходные тексты приложения вручную непосредственно в текстовом редакторе. Но во многих случаях среда VIsual C++ может оказать вам значительную помощь. Одним из средств, способных оказать вам такую помощь уже сейчас, является ClassView.

Используя ClassView можно быстро добавлять к классам новые элементы, просматривать структуру наследования классов и выполнять другие полезные операции. После того как вы разберетесь с основными принципами построения приложений Windows с использованием классов MFC, мы продолжим изучение вспомогательных средств VIsual C++. В следующих главах книги мы рассмотрим средства автоматизированного проектирования приложений MFC AppWizard и средство для разработки классов ClassWizard.

А сейчас приступим к описанию возможностей ClassView. Выберите из списка ClassView название класса, который вы желаете просмотреть или изменить, и нажмите правую клавишу мыши. На экране появится временное меню, представленное на рисунке 2.14.

Рис. 2.14. Временное меню класса

Строки этого меню позволяют выполнять над классами все основные действия. Строка Go to Definition позволяет просмотреть в окне редактирования исходный текст класса. Вы можете редактировать класс непосредственно, но для добавления в класс новых методов и данных удобнее пользоваться строками Add Function и Add Variable.

Добавление к классу нового метода

Чтобы добавить в класс новый метод, выберите из временного меню строку Add Function. На экране появится диалоговая панель Add Member Function, представленная на рисунке 2.15.

Рис. 2.15. Диалоговая панель Add Member Function

В поле Function Type следует ввести тип значения, возвращаемого методом. Объявление метода запишите в поле Function Declaration. В этой же диалоговой панели можно определить область видимости метода. Для этого предназначен переключатель с зависимой фиксацией Access. Он может находиться в трех положениях: Public, Protected и Private. Переключатели Static и Virtual позволяют определить, что добавляемый метод должен быть объявлен, соответственно, как статический или виртуальный.

Когда все поля диалоговой панели заполнены, нажмите кнопку OK. В объявлении класса будет добавлен новый метод. Название метода также появится в списке элементов класса в окне ClassView.

Добавление к классу нового элемента данных

Процедура добавления в класс новых данных сходна с только что описанной процедурой добавления метода. Для этого выберите из меню строку Add Variable. На экране появится диалоговая панель Add Member Variable, представленная на рисунке 2.16.

Рис. 2.16. Диалоговая панель Add Member Variable

В поле Variable Type надо ввести тип данных, а в поле Variable Declaration – название соответствующей переменной. Область видимости переменной определяется переключателем Access.

С помощью ClassView можно просмотреть список названий файлов в которых используется данный класс. Для этого надо выбрать из временного меню строку References. На экране появится диалоговая панель Definitions and References.

Просмотр дерева наследования классов

ClassView предоставляет очень интересную и полезную возможность просмотра дерева наследования классов приложения. Для этого выберите название интересующего вас класса из списка классов и откройте временное меню, нажав правую кнопку мыши. Строки Derived Classes и Base Classes позволяют просмотреть последовательность классов, порожденных от данного класса или последовательность базовых классов.

На рисунке 2.17 мы воспользовались возможностями ClassView для изучения последовательности базовых классов для основного класса приложения MFHello.

Рис. 2.17. Порядок наследования, диалоговая панель Base Classes and Members

Диалоговая панель Base Classes and Members не имеет кнопок OK и Cancel. Она закрывается в том случае, если вы выберите из нее элемент класса или переключитесь на другое окно. Иногда удобно, чтобы диалоговая панель постоянно присутствовала на экране. Вы можете “прикрепить” ее к главному окну Microsoft Visual C++. Нажмите кнопку , она изменится на . Теперь в любой момент времени вы сможете открыть панель Base Classes and Members.

В левой части этой панели отображается список классов в порядке наследования. Базовые классы расположены ниже и правее наследуемых классов. Вы наглядно можете определить, что основным базовым классом для CMFHelloApp является класс CObject. Из этого класса наследуются классы CCmdTarget, CWinThread, CWinApp и только затем класс CMFHelloApp, определенный в приложении.

В правой части экрана отображаются элементы класса, выбранного из списка классов. Вы можете просмотреть не только элементы классов, определенных в приложении, но также и элементы классов из библиотеки MFC. Все элементы класса разделены на три группы в зависимости от их области видимости – Public, Protected и Private.

Панель Base Classes and Members позволяет легко перейти к редактированию любого элемента класса. Для этого выберите название этого элемента из списка и сделайте по нему двойной щелчок левой кнопкой мыши.

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

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

Тип метода Отображать
All Все методы
Virtual Виртуальные методы
Static Статические методы
Non–Static Все методы, кроме статических
Non–Virtual Все методы, кроме виртуальных
Non–Static Non-Virtual Все методы, кроме статических и виртуальных
None Не отображать методы класса

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

Тип элементов данных Отображать
All Все элементы данных
Static Статические элементы данных
Non–Static Все данные, кроме статических
None Не отображать элементы данных

В нижней правой части диалоговой панели Base Classes and Members отображаются названия файлов в которых определен (группа Definitions), и в которых используется (группа References) выбранный элемент. Двойной щелчок левой кнопкой мыши позволяет открыть в редакторе соответствующий файл. Курсор при этом сразу устанавливается в то место, где объявляется или используется выбранный элемент класса.

Редактирование методов класса

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

Рис. 2.18. Временное меню метода

Чтобы открыть в редакторе файл, в котором объявляется метод и перейти к его редактированию, выберите из временного меню метода строку Go to Definition. После того как вы добавите в класс новый метод, ClassWizard создаст шаблон метода. Строка Go to Declaration из временного меню метода позволяет изменить этот шаблон по вашему усмотрению.

Возможности ClassView можно использовать даже на этапе отладки приложения. Так, из временного меню метода можно установить точку прерывания непосредственно на начало метода. Для этого выберите из меню строку Set Breakpoint.

Редактирование элементов данных класса

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

Рис. 2.19. Временное меню метода

Приложение с единственным окном

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

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

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

Создайте новый проект, как мы рассказывали выше, и назовите его именем MFStart. В качестве типа приложения выберите из списка Type строку Application (рис. 4.1 из главы “Приложение с главной диалоговой панелью”). Автоматизированные средства разработки приложений MFC AppWizard мы рассмотрим позже.

Наберите в редакторе исходный текст приложения и сохраните его в файле MFStart.cpp (листинг 2.2). Наш пример без учета строк комментариев состоит всего из двадцати строк исходного текста, поэтому набор текста не займет у вас много времени. Включите набранный файл в проект.

Листинг 2.2. Файл MFStart.cpp

// Включаемый файл для MFC

// Наследуем от базового класса CWinApp главный

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

class CMFStartApp : public CWinApp <

// Мы будем переопределять метод InitInstance,


// предназначенный для инициализации приложения

virtual BOOL InitInstance();

// Создаем объект приложение класса CMFStartApp

// Наследуем от базового класса CFrameWnd класс

// CMFStartWindow. Он будет представлять главное

// окно нашего приложения

class CMFStartWindow : public CFrameWnd <

// Объявляем конструктор класса CMFStartWindow

// Метод InitInstance класса CMFStartApp

// Переопределяем виртуальный метод InitInstance

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

// Создаем объект класса CMFStartWindow

m_pMainWnd = new CMFStartWindow();

// Отображаем окно на экране. Параметр m_nCmdShow

// определяет режим в котором оно будет отображаться

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

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

// Создаем окно приложения, соответствующее

// данному объекту класса CMFStartWindow

Create(NULL, «Hello MFC»);

Просмотрите папку с файлами проекта. Теперь в ней расположен файл MFStart.cpp. Затем откройте страницу ClassView в окне Project Workspace (рис. 2.20). В ней отображаются два класса CMFStartApp и CMFStartWindow. В класс CMFStartApp входит метод InitInstance, а в класс CMFStartWindow конструктор CMFStartWindow. Кроме того, определена глобальная переменная MFStartApp.

Рис. 2.20. Классы проекта MFStart

Постройте проект и запустите полученное приложение, выбрав из меню Build строку Execute MFStart.exe. На экране появится главное окно приложения, представлене нами на рисунке 2.21. Оно имеет стандартный заголовок с надписью Hello MFC, системное меню и кнопки для изменения размера окна. Чтобы завершить приложение, вы можете выбрать строку Close из системного меню главного окна или нажать на кнопку .

Рис. 2.21. Приложение MFStart

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

Так же как и у приложения MFHello, первая строка исходного текста приложения MFStart, не считая строки комментария, содержит директиву препроцессора #include, которая включает файл afxwin.h. Этот файл включается в исходные тексты всех приложений, использующих библиотеку классов MFC.

Затем мы определяем главный класс приложения, который наследуется от базового класса CWinApp . Главный класс приложения MFHello, который называется CMFStartApp, определяется следующим образом:

// Наследуем от базового класса CWinApp главный

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

class CMFStartApp : public CWinApp <

// Мы будем переопределять метод InitInstance,

// предназначенный для инициализации приложения

virtual BOOL InitInstance();

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

После объявления главного класса приложения мы создаем объект этого класса – MFStartApp:

// Создаем объект приложение класса CMFStartApp

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

// Наследуем от базового класса CFrameWnd класс

// CMFStartWindow. Он будет представлять главное

// окно нашего приложения

class CMFStartWindow : public CFrameWnd <

// Объявляем конструктор класса CMFStartWindow

Метод InitInstance главного класса приложения CMFStartApp служит для инициализации. Он вызывается автоматически каждый раз, когда запускается очередная копия приложения.

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

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

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

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

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

Если метод InitInstance вернет значение FALSE, приложение немедленно завершится. Мы использовали эту возможность в приложении MFHello, описанном выше.

// Метод InitInstance класса CMFStartApp

// Переопределяем виртуальный метод InitInstance

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

// Создаем объект класса CMFStartWindow

m_pMainWnd = new CMFStartWindow();

// Отображаем окно на экране. Параметр m_nCmdShow

// определяет режим в котором оно будет отображаться

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

Чтобы создать окно, мы создаем объект класса CMFStartWindow. Такой объект не является собственно окном, которое пользователь видит на экране компьютера, а представляет собой внутреннее представление окна. Для создания окна предназначается метод Create, определенный в классе CFrameWnd. Он создает окно и связывает его с объектом Си++, в нашем случае с объектом класса CMFStartWindow:

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

// Создаем окно приложения, соответствующее

// данному объекту класса CMFStartWindow

Create(NULL, «Hello MFC»);

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

Например, мы могли бы поместить описание классов CMFStartApp и CMFStartWindow в файлы MFStartApp.h и MFStartWindow.h. Метод InitInstance класса CMFStartApp и определение глобальной переменной MFStartApp можно поместить в файл MFStartApp.cpp, а определение конструктора класса CMFStartWindow – в файл MFStartWindow.cpp.

Так как в методе InitInstance класса CMFStartApp мы создаем новый объект класса CMFStartWindow, то мы должны включить в файл MFStartApp.cpp не только файл MFStartApp.h но еще и файл MFStartWindow.h. В проект MFStart мы должны записать оба программных файла MFStartApp.cpp и MFStartWindow.cpp. Листинги, представленные ниже содержат проект MFStart, разделенный на несколько файлов. Для того, чтобы сократить размер файлов, мы убрали из них комментарии.

Файл MFStartApp.h содержит описание главного класса приложения CMFStartApp. Этот файл представлен в листинге 2.3.

Листинг 2.3. Файл MFStartApp.h

class CMFStartApp : public CWinApp <

virtual BOOL InitInstance();

Виртуальный метод InitInstance переопределен нами в файле MFStartApp.cpp. В этом же файле создается объект класса CMFStartApp, представляющий само приложение. Файл MFStartApp.cpp показан в листинге 2.4.

Листинг 2.4. Файл MFStartApp.cpp

m_pMainWnd = new CMFStartWindow();

Класс окна приложения CMFStartWindow определяется в файле MFStartWindow.h, представленном листингом 2.5. Мы наследуем класс CMFStartWindow от базового класса CFrameWnd.

Листинг 2.5. Файл MFStartWindow.h

class CMFStartWindow : public CFrameWnd <

И наконец, последний файл MFStartWindow.cpp модифицированного проекта MFStart показан в листинге 2.6. В этом файле определяется конструктор класса CMFStartWindow.

Листинг 2.6. Файл MFStartWindow.cpp

Create(NULL, «Hello MFC»);

Как вы знаете из предыдущих томов серии “Библиотека системного программиста”, работа приложений операционной системы Windows основана на обработке сообщений. Когда пользователь работает с устройствами ввода/вывода компьютера, например клавиатурой или мышью, драйверы этих устройств создают сообщения, описывающие его действия. Каждое нажатие на клавиши клавиатуры вызывает генерацию ряда сообщений, определяющих, какая клавиша нажата. Перемещение мыши вызывает сообщения, описывающие траекторию перемещения указателя мыши и т. д. Другие сообщения могут вырабатываться операционной системой или самими приложениями.

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

Приложение в цикле, который называется циклом обработки сообщений, получает сообщения из очереди приложения и направляет их соответствующей функции окна, которая и выполняет обработку сообщения. Цикл обработки сообщений обычно состоял из оператора while в котором циклически вызывались функции GetMessage и DispatchMessage:

while(GetMessage(&message, 0, 0, 0)) <

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

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

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

long FAR PASCAL _export WndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam) <

return DefWindowProc(hwnd, message, wParam, lParam);

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

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

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

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

• сообщения от органов управления;

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

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

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

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

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

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

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

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

В приложении MFMenu строка Beep меню Test имеет идентификатор ID_TEST_BEEP. Когда пользователь выберет данную строку, в очередь приложения поступит сообщение WM_COMMAND с идентификатором ID_TEST_BEEP или другими словами, командное сообщение ID_TEST_BEEP.

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

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

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

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

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

• Стандартные сообщения Windows обрабатываются функцией “default window procedure”

• Командные сообщения передаются по цепочке следующему объекту, который может обработать командное сообщение. Более подробно мы расскажем об этой цепочке в главах “Однооконный интерфейс” и “Многооконный интерфейс”

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

Макрокоманда Устанавливает методы для обработки сообщений
ON_WM_ Стандартных сообщений операционной системы Windows
ON_REGISTERED_MESSAGE Зарегистрированные сообщения операционной системы Windows
ON_MESSAGE Сообщений, определенных пользователем
ON_COMMAND, ON_COMMAND_RANGE Командных сообщений
ON_UPDATE_COMMAND_UI, ON_UPDATE_COMMAND_UI_RANGE Сообщений, предназначенных для обновления пользовательского интерфейса
ON_ , ON_CONTROL_RANGE Сообщений от органов управления

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

Обрабатывает стандартные сообщения операционной системы Windows. Вместо указывается имя сообщения без префикса WM_. Так, например для обработки сообщения WM_SIZE предназначена макрокоманда ON_WM_SIZE.

Для обработки сообщений, определенных в таблице сообщений макрокомандами ON_WM_ , вызываются одноименные методы. Имя метода обработчика соответствует названию сообщения, без учета префикса WM_.

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

Сообщение Макрокоманда Метод обработчик
WM_CHAR ON_WM_CHAR() afx_msg void OnChar(UINT, UINT, UINT);
WM_CREATE ON_WM_CREATE() afx_msg int OnCreate(LPCREATESTRUCT);
WM_HSCROLL ON_WM_HSCROLL() afx_msg void OnHScroll(UINT, UINT, CWnd*);
WM_KEYDOWN ON_WM_KEYDOWN() afx_msg void OnKeyDown(UINT, UINT, UINT);
WM_KEYUP ON_WM_KEYUP() afx_msg void OnKeyUp(UINT, UINT, UINT);
WM_LBUTTONDOWN ON_WM_LBUTTONDOWN() afx_msg void OnLButtonDown(UINT, CPoint);
WM_LBUTTONUP ON_WM_LBUTTONUP() afx_msg void OnLButtonUp(UINT, CPoint);
WM_PAINT ON_WM_PAINT() afx_msg void OnPaint();
WM_SIZE ON_WM_SIZE() afx_msg void OnSize(UINT, int, int);
WM_TIMER ON_WM_TIMER() afx_msg void OnTimer(UINT);
WM_VSCROLL ON_WM_VSCROLL() afx_msg void OnVScroll(UINT, UINT, CWnd*);

Все методы-обработчики определены с ключевым словом afx_msg. Оно позволяет отличить эти методы от остальных методов класса. На этапе препроцессорной обработки ключевое слово afx_msg удаляется. Определение afx_msg вы можете найти в файле afxwin.h:

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

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

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

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

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

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

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

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

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

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

ON_COMMAND_RANGE(id1, id2, memberFxn)

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

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

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

afx_msg void OnUpdate (CCmdUI* pCmdUI);

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

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

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

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

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

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

ON_UPDATE_COMMAND_UI_RANGE(id1, id2, memberFxn)

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

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

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

ON_CONTROL_RANGE(wNotifyCode, id1, id2, memberFxn)

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

Однако ClassWizard не всесилен. Так он не позволяет определить один метод для обработки нескольких сообщений. Как вы уже знаете, для этих целей предназначены макрокоманды ON_COMMAND_RANGE и ON_CONTROL_RANGE. Если вы решите воспользоваться этими макрокомандами, вам придется редактировать таблицу сообщений непосредственно, без использования ClassWizard.

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

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

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

Создайте новый проект под названием MFMenu. В качестве типа приложения выберите из списка Type строку Application (рис. 4.1 из главы “Приложение с главной диалоговой панелью”). Наберите в редакторе исходный текст приложения и сохраните его в файле MFMenu.cpp (листинг 2.7). Чтобы быстрее набрать текст приложения, вы можете получить его, изменив исходный текст приложения MFStart. Затем включите этот файл в проект.

Листинг 2.7. Файл MFMenu.cpp

// Включаемый файл для MFC

// Класс CMFMenuApp – главный класс приложения

class CMFMenuApp : public CWinApp <

// Мы будем переопределять метод InitInstance,

// предназначенный для инициализации приложения

virtual BOOL InitInstance();

// Создаем объект приложение класса CMFMenuApp

// Класс CMFMenuWindow – представляет главное окно

class CMFMenuWindow : public CFrameWnd <

// Объявляем конструктор класса CMFMenuWindow

// Объявляем методы для обработки команд меню

afx_msg void MenuCommand();

afx_msg void ExitApp();

// Макрокоманда необходима, так как класс

// CMFMenuWindow обрабатывает сообщения

// Обрабатывает команду ID_TEST_BEEP

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

// Метод InitInstance класса CMFMenuApp

// Создаем объект класса CMFMenuWindow

m_pMainWnd = new CMFMenuWindow();

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

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

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

// Создаем окно приложения, соответствующее

// данному объекту класса CMFMenuWindow

Create(NULL, «Hello MFC», WS_OVERLAPPEDWINDOW, rectDefault, NULL, MAKEINTRESOURCE(IDR_MENU));

Добавить в проект новый ресурс очень просто. Вы можете для этого воспользоваться кнопками панели управления Progect или установить указатель мыши на название типа ресурса и нажать правую кнопку мыши. На экране появится временное меню свойств данного ресурса.

Если у вас уже есть ресурсы, которые разработаны ранее и записаны в отдельных файлах на диске, вы можете подключить их к своему проекту. Для этого надо выбрать из временного меню свойств ресурса строку Import. На экране появится диалоговая панель Import Resource с приглашением ввести имя файла подключаемого вами ресурса. Новый ресурс проекта будет записан в подкаталог RES, расположенный в каталоге проекта.

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

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

Создание меню для приложения MFMenu

Так как наше приложение будет содержать меню, мы приступим к созданию ресурсов приложения. Для этого создайте новый файл ресурсов. Выберите из меню File строку New, а затем из открывшейся диалоговой панели выберите строку Resource Script и нажмите кнопку OK.

Теперь надо создать меню. Выберите из меню Insert строку Resource. На экране появится диалоговая панель Insert Resource. Выберите из нее строку Menu и нажмите кнопку OK. Вы сможете в диалоговом режиме разработать меню. Чтобы быстрее перейти к редактированию меню, вы можете нажать кнопку New Menu ( ) из панели управления Project или просто нажать комбинацию кнопок .

Создайте меню, содержащее единственную строку Test, при выборе которой открывается меню, содержащее три строки – Beep и Exit. Внешний вид меню во время разработки представлен на рисунке 2.22.

Рис. 2.22. Разработка меню приложения

Когда вы создаете новое меню верхнего уровня или определяете строки, входящие в это меню, на экране появляется диалоговое окно Menu Item Properties (рис. 2.23). В нем полностью описывается выбранный элемент меню. В поле Caption задается название меню или строки меню. В названии вы можете вставить символ &. Он будет означать, что символ, следующий за ним, можно будет использовать для быстрого выбора данного элемента меню. Например, если перед названием строки меню Beep поставить символ &, то во время работы приложения символ B будет отображаться с подчеркиванием, и строку B eep можно будет выбрать, нажав комбинацию клавиш .

Рис. 2.23. Диалоговая панель Menu Item Properties

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

Редактор ресурсов сам предлагает вам название идентификатора, создавая его из названия главного меню и строки меню. Так например строке Beep меню Test по умолчанию будет присвоен идентификатор ID_TEST_BEEP.

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

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

Остальные переключатели диалоговой панели Menu Item Properties описаны в следующей таблице.

Переключатель Описание
Break Этот переключатель может принимать три различных значения – None, Column и Bar. Он позволяет задать структуру меню. По умолчанию выбрано значение None оно соответствует нормальному виду меню без деления на колонки. Если выбрать значение Column, тогда пункт меню будет размещен в новом столбце. Значение Bar соответствует Column, за исключением меню верхнего уровня. Если указать Bar для меню верхнего уровня, то новая колонка будет отделена от старой вертикальной линией
Checked Если установить переключатель, то строка меню будет выделена символом √. Потом, обращаясь к специальным методам, вы сможете удалять или отображать этот символ
Grayed Если включить переключатель Grayed, тогда пункт меню будет отображаться серым цветом и будет недоступен для выбора пользователем. Такая возможность удобна, если вам надо сделать недоступным какие-либо возможности приложения. Впоследствии приложение может сделать пункт меню доступным. Для этого надо вызвать соответствующий метод
Help Если установить переключатель Help, тогда для него будет установлено выравнивание по правому краю. Обычно этот переключатель устанавливают для меню верхнего уровня, которое управляет справочной системной приложения
Inactive Если включен переключатель Grayed, тогда переключатель недоступен. В противном случае вы можете установить переключатель Inactive. В этом случае пункт меню будет неактивен
Pop-up Вы можете создавать многоуровневые меню. Если вы включите переключатель Pop-up, то данный пункт меню будет являться меню верхнего уровня, которое можно открыть. По умолчанию, все пункты главного меню имеют установленный переключатель Pop-up. Так как меню верхнего уровня служит только для объединения других пунктов меню, то оно не имеет идентификатора
Separator Если переключатель установлен, тогда в меню вставляется разделитель. Для разделителя все остальные поля и переключатели диалоговой панели не используются

Сохраните файл ресурсов в файле с именем MFMenu.rc. Редактор ресурсов создает кроме самого файла ресурсов еще включаемый файл, в котором определяются константы, используемые в файле ресурсов. В нашем случае в нем определяются идентификаторы меню приложения. По умолчанию этот файл сохраняется под именем resource.h . Вы можете изменить его, выбрав из меню View строку Resource Includes. Для нашего приложения мы изменили имя включаемого файла для ресурсов на MFMenuRes.h. Содержимое этого файла представлено листингом 2.8.

Листинг 2.8. Файл MFMenuRes.h

// Включаемый файл, созданный Microsoft Developer Studio

// Используется в файле ресурсов MFMenu.rc

#define IDR_MENU 101

#define ID_TEST_BEEP 40001

#define ID_TEST_EXIT 40002

// Следующие значения идентификаторов используются по

// умолчанию для новых объектов

#define _APS_NEXT_RESOURCE_VALUE 102

#define _APS_NEXT_COMMAND_VALUE 40003

#define _APS_NEXT_CONTROL_VALUE 1000

#define _APS_NEXT_SYMED_VALUE 101

В листинге 2.9 мы привели файл ресурсов MFMenuRes.rc приложения. Этот файл был подготовлен редактором ресурсов Visual C++. Одна из первых строк файла содержит директиву #include которой подключается файл MFMenuRes.h, содержащий описание идентификаторов ресурсов (листинг 2.8).

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

Листинг 2.9. Файл MFMenuRes.rc

// Файл описания ресурсов приложения, созданный

// Microsoft Developer Studio

// Включаем файл afxres.h, содержащий определения стандартных

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)

LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT

IDR_MENU MENU DISCARDABLE

MENUITEM «Beep», ID_TEST_BEEP

MENUITEM «Exit», ID_TEST_EXIT

1 TEXTINCLUDE DISCARDABLE

2 TEXTINCLUDE DISCARDABLE

3 TEXTINCLUDE DISCARDABLE

#endif // Руссификацированные ресурсы

Когда вы создадите ресурсы приложения и включите файл ресурсов в проект обратите внимание на окно Project Workspace. В нем появится еще одна, четвертая страница ResourceView (рис. 2.24). Эта страница показывает все ресурсы, входящие в проект. В приложении MFMenu определен только один ресурс – меню, имеющее идентификатор IDR_MENU.

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

Рис. 2.24. Страница ResourceView окна Project Workspace

Теперь проект готов. Вы можете построить его и запустить полученное приложение MFMenu. Внешний вид приложения представлен на рисунке 2.25. Как видите окно приложения имеет меню Test, состоящее из двух строк – Beep и Exit.

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

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

Рис. 2.25. Приложение MFMenu

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

// Класс CMFMenuWindow – представляет главное окно

class CMFMenuWindow : public CFrameWnd <

// Объявляем конструктор класса CMFMenuWindow

// Объявляем методы для обработки команд меню

afx_msg void MenuCommand();

afx_msg void ExitApp();

// Макрокоманда необходима, так как класс

// CMFMenuWindow обрабатывает сообщения

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

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

Приложение MFMenu обрабатывает только две команды от меню приложения. Первая команда имеет идентификатор ID_TEST_BEEP и передается, когда пользователь выбирает из меню Test строку Beep. Для обработки этой команды вызывается метод MenuCommand. Вторая команда с идентификатором ID_TEST_EXIT передается приложению, когда пользователь выбирает из меню Test строку Exit. Обработка этого сообщения выполняется методом ExitApp.

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

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

Долгий путь сообщения

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

Создайте новый проект под названием MFMessage. В качестве типа приложения выберите из списка Type строку Application (рис. 4.1). Наберите в редакторе исходный текст приложения и сохраните его в файле MFMessage.cpp (листинг 2.10). Чтобы быстрее набрать текст приложения, вы можете модифицировать исходный текст приложения MFMenu.

Листинг 2.10. Файл MFMessage.cpp

// Включаемый файл для MFC

// Класс CMFMessageApp – главный класс приложения

class CMFMessageApp : public CWinApp <

// Мы будем переопределять метод InitInstance,

// предназначенный для инициализации приложения

virtual BOOL InitInstance();

afx_msg void AppMessageCommand();

// Макрокоманда необходима, так как класс

// CMFMessageWindow обрабатывает сообщения

// Создаем объект приложение класса CMFMessageApp

// Класс CMFMessageWindow – представляет главное окно

class CMFMessageWindow : public CFrameWnd <

// Объявляем конструктор класса CMFMessageWindow

// Объявляем методы для обработки команд меню

afx_msg void FrameMessageCommand();

afx_msg void ExitApp();

// Макрокоманда необходима, так как класс

// CMFMessageWindow обрабатывает сообщения

// Обрабатывает команду ID_TEST_BEEP

::MessageBox(NULL, «Command received in CMFMessageWindow Message Map», «Message», MB_OK);

// Обрабатывает команду ID_TEST_BEEP

::MessageBox(NULL, «Command received in CMFMessageApp Message Map», «Message», MB_OK);

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

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

// Метод InitInstance класса CMFMessageApp

// Создаем объект класса CMFMessageWindow

m_pMainWnd = new CMFMessageWindow();

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

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

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

// Создаем окно приложения, соответствующее

// данному объекту класса CMFMessageWindow

Create(NULL, «Hello MFC», WS_OVERLAPPEDWINDOW, rectDefault, NULL, MAKEINTRESOURCE(IDR_MENU));

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

Строка меню Test Идентификатор
In Frame Class ID_TEST_INFRAMECLASS
In App Class ID_TEST_INAPPCLASS
In Both Class ID_TEST_INBOTHCLASS
Exit ID_APP_EXIT

В листинге 2.11 представлен фрагмент файла ресурсов MFMessage.rc, в котором определяется меню приложения. Чтобы ускорить разработку меню, вы можете скопировать меню приложения MFMenu и изменить его соответствующим образом.

Листинг 2.11. Фрагмент файла MFMessage.rc

IDR_MENU MENU DISCARDABLE

MENUITEM «In Frame Class», ID_TEST_INFRAMECLASS

MENUITEM «In App Class», ID_TEST_INAPPCLASS

MENUITEM «In Both Class», ID_TEST_INBOTHCLASS

MENUITEM «Exit», ID_APP_EXIT

Идентификаторы, необходимые для файла ресурсов, записываются в файл resource.h, показанный в листинге 2.12. Этот файл создается автоматически редактором ресурсов. Все что вы должны сделать – это включить его в исходный текст приложения – файл MFMessage.cpp.

Листинг 2.12. Файл resource.h

// Включаемый файл, созданный Microsoft Developer Studio

// Используется в файле ресурсов MFMessage.rc

#define IDR_MENU 101

#define ID_TEST_BEEP 40001

#define ID_TEST_EXIT 40002

#define ID_TEST_INAPPCLASS 40003

#define ID_TEST_INFRAMECLASS 40004

#define ID_TEST_INBOTHCLASS 40006

// Следующие значения идентификаторов используются по

// умолчанию для новых объектов

#define _APS_3D_CONTROLS 1


#define _APS_NEXT_RESOURCE_VALUE 102

#define _APS_NEXT_COMMAND_VALUE 40007

#define _APS_NEXT_CONTROL_VALUE 1000

#define _APS_NEXT_SYMED_VALUE 101

Укажите в проекте MFMessage, что приложение использует библиотеку классов MFC и постройте проект. Запустите полученный выполнимый файл. На экране появится главное окно приложение, имеющее меню Test (рис. 2.26).

Рис. 2.26. Приложение MFMessage

Когда вы выбираете строки из меню Test, приложению передаются команды с соответствующими идентификаторами. Обратите внимание, что команда ID_TEST_INFRAMECLASS обрабатывается в классе окна CMFMessageWindow, команда ID_TEST_INAPPCLASS в главном классе приложения CMFMessageApp. Команда ID_TEST_INBOTHCLASS содержит два обработчика – один в классе окна, другой в классе приложения, зато команда ID_APP_EXIT не имеет обработчика совсем.

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

Поэкспериментируйте с приложением MFMessage. Очень скоро вы обнаружите, что команды обрабатываются не только классом окна, как это было в приложении MFMenu, но также и главным классом приложения. Те команды которые не имеют обработчика в таблице сообщений класса окна, передаются для обработке в класс приложения.

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

Широкие возможности для управления обработкой сообщений предоставляет ClassWizard. Мы расскажем более подробно об обработке сообщений и средствах ClassWizard в следующей главе.

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

Библиотека классов MFC содержит класс CDialog, специально предназначенный для управления диалоговыми панелями. Как мы рассказывали в предыдущих томах серии “Библиотека системного программиста”, посвященных программированию для операционных систем Windows и Windows 95, диалоговые панели бывают двух типов – модальные и немодальные.

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

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

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

Рис. 2.27. Класс CDialog

В библиотеке MFC версии 1.0 для немодальных диалоговых панелей был предназначен отдельный класс CModalDialog. Однако, начиная с MFC версии 2.0 он включен в класс CDialog. Для совместимости класс CModalDialog также оставлен, но он определен макрокомандой #define как CDialog (файл Afxwin.h):

#define CModalDialog CDialog

Как создать и отобразить на экране диалоговую панель? В первую очередь необходимо добавить в файл ресурсов приложения шаблон новой диалоговой панели и при помощи редактора ресурсов изменить его по своему усмотрению.

Следующим этапом создается класс для управления диалоговой панелью. Этот класс наследуется непосредственно от базового класса CDialog.

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

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

Чтобы создать модальную диалоговую панель, сначала необходимо создать объект определенного вами класса диалоговой панели, а затем вызвать метод DoModal, определенный в классе CDialog.

Процедура создания немодальной диалоговой панели несколько другая. Для этого используется метод Create класса CDialog. Мы рассмотрим создание немодальных диалоговых панелей позже.

Приложение с модальной диалоговой панелью

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

Создайте новый проект под названием MFDialog. В качестве типа приложения выберите из списка Type строку Application (рис. 4.1). Наберите в редакторе исходный текст приложения и сохраните его в файле MFDialog.cpp (листинг 2.13).

Листинг 2.13. Файл MFDialog.cpp

// Включаемый файл для MFC

// Класс CMFDialogApp – главный класс приложения

class CMFDialogApp : public CWinApp <

// Мы будем переопределять метод InitInstance,

// предназначенный для инициализации приложения

virtual BOOL InitInstance();

// Создаем объект приложение класса CMFDialogApp

// Класс CMyDialog – класс диалоговой панели

class CMyDialog : public CDialog <

virtual void DoDataExchange(CDataExchange* pDX);

// Обработчики сообщений от кнопок диалоговой панели

afx_msg void OnDefault();

virtual void OnCancel();

virtual void OnOK();

// Макрокоманда необходима, так как класс

// CMyDialog обрабатывает сообщения от органов

// управления диалоговой панели

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

// Инициализируем переменную m_Text

// Метод DoDataExchange класса CMyDialog

void CMyDialog::DoDataExchange(CDataExchange* pDX) <

DDX_Text(pDX, IDC_EDIT, m_Text);

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

// Метод OnDefault класса CMyDialog

m_Text = «Start Text»;

// Метод OnCancel класса CMyDialog

// Подаем звуковой сигнал

// Вызываем метод OnCancel базового класса

// Метод OnOK класса CMyDialog

// Вызываем метод OnOK базового класса

// Подаем звуковой сигнал

// Метод InitInstance класса CMFDialogApp

// Создаем объект класса CMyDialog

// Отображаем на экране модельную диалоговую панель

// Отображаем на экране значение переменной m_Text,

// ввходящей в класс CMyDialog

Создайте файл ресурсов MFDlgRes.rc и добавьте в него новую диалоговую панель. На экране откроется окно редактора диалоговой панели и панель с инструментами Controls (рис. 2.28). По умолчанию новая диалоговая панель называется Dialog и содержит две кнопки OK и Cancel.

Вы можете добавлять в диалоговую панель другие органы управления – кнопки, переключатели, поля редактирования, статические текстовые поля, рисунки. Более того в Visual C++ версии 4.0 вам становятся доступны новые органы управления – многостраничные диалоговые панели, поля для просмотра видеоинформации и т. д.

Рис. 2.28. Создание диалоговой панели

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

Кнопка Название Описание

Select Если вы нажмете эту кнопку, то сможете выбрать органы управления, которые уже расположены в диалоговой панели

Static Text Статическое текстовое поле

Edit Box Поле редактирования

Group Box Прямоугольник, объединяющий группу органов управления

Check Box Переключатель в виде прямоугольника

Radio Button Переключатель круглой формы (радиопереключатель)

Combo Box Список с окном редактирования

List Box Список

Horizontal Scroll Bar Горизонтальная полоса просмотра

Vertical Scroll Bar Вертикальная полоса просмотра

Animate Окно просмотра видео

Tab Control Позволяет размещать в диалоговой панели несколько страниц органов управления, каждая из которых имеет “закладку”. Пользователь одновременно видит закладки всех страниц и может выбрать любую из них.

Tree Control Позволяет просматривать иерархические (древовидные) структуры данных. Такой орган управления можно использовать для отображения структуры каталогов на диске, заголовков статей справочной системы и т. д.

List Control Может использоваться для отображения списка пиктограмм

Hot Key Орган управления Hot Key предназначен для ввода комбинации клавиш акселераторов

Slider Движок. Обычно используется при отображении видеоинформации. Позволяет перейти к просмотру произвольного кадра

Progress Линейный индикатор. Позволяет отображать на экране ход какого-нибудь процесса, например процесса копирования файлов

Spin Обычно используется для увеличения или уменьшения значения какого-нибудь параметра

Custom Control Орган управления, внешний вид и назначение которого определяется пользователем

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

Сначала добавьте кнопку. Для этого щелкните по изображению кнопки в панели Controls. Затем переместите указатель мыши в то место диалоговой панели, где вы желаете разместить кнопку и нажмите левую клавишу мыши. В диалоговой панели появится изображение кнопки, названное по умолчанию Button1. Выполните по ней двойной щелчок левой клавишей мыши. На экране появится панель Push Button Propeties, определяющая различные характеристики кнопки. В первую очередь вас будут интересовать поля Caption и ID. В поле Caption введите название кнопки Default, а в поле ID ее идентификатор IDC_DEFAULT. Остальные характеристики кнопки оставьте без изменения.

Находясь в редакторе ресурсов вы можете сразу попробовать как работает диалоговая панель. Найдите диалоговую панель Dialog (рис. 2.29). Если ее нет на экране, выберите из меню View строку Toolbars и в открывшейся диалоговой панели Toolbars установите переключатель Dialog. Диалоговая панель Dialog содержит ряд кнопок. Первая кнопка, на которой нарисован тумблер, позволяет проверить, как будет работать диалоговая панель.

Рис. 2.29. Панель управления Dialog

Остальные кнопки диалоговой панели Dialog позволяют задавать выравнивание органов управления друг относительно друга и относительно границ панели. Последние две кнопки устанавливают разметку на диалоговой панели. Разметка поможет вам ровнее разместить органы управления.

Вы можете изменить заголовок диалоговой панели, ее идентификатор и многие другие параметры, если сделаете двойной щелчок левой кнопкой мыши по заголовку диалоговой панели. На экране появится панель Dialog Properties, содержащая несколько страниц. Выберите страницу General (рис. 2.30).

Рис. 2.30. Характеристики диалоговой панели

В поле ID вы можете изменить идентификатор диалоговой панели, в поле Caption – заголовок диалоговой панели. В полях Font name и Font size отображается тип и размер шрифта, который используется для всех текстов в диалоговой панели. Изменить параметры шрифта можно, нажав кнопку Font. Поля X Pos и Y Pos позволяют указать начальное положение диалоговой панели на экране. Если X Pos и Y Pos содержат нулевые значения, начальное положение диалоговой панели определяется операционной системой.

Диалоговая панель может иметь собственное меню. Это меню будет отображаться непосредственно под заголовком диалоговой панели. Если вы желаете подключить к диалоговой панели меню, сначала разработайте меню и запишите его в файл ресурсов. Затем выберите в диалоговой панели Dialog Properties идентификатор данного меню из списка Menu.

Для приложения MFDialog вам надо поменять только идентификатор диалоговой панели и ее название. Измените идентификатор диалоговой панели с IDD_DIALOG1 на “DIALOGPANEL”, а ее заголовок – с Dialog на My Dialog. Остальные характеристики диалоговой панели оставьте без изменения.

Итак, диалоговая панель “DIALOGPANEL” приложения MFDialog содержит три кнопки, одно статическое текстовое поле и одно поле редактирования. В листинге 2.14 представлен фрагмент файла ресурсов в котором определяется диалоговая панель приложения.

Листинг 2.14. Фрагмент файла MFDlgRes.rc

DIALOGPANEL DIALOG DISCARDABLE 0, 0, 186, 46

CAPTION «My Dialog»

FONT 8, «MS Sans Serif»

LTEXT «Line Editor»,IDC_STATIC,9,10,34,8

Идентификаторы, задействованные в файле ресурсов приложения по умолчанию, определяются во включаемом файле resource.h. Мы привели этот файл в листинге 2.15. Вы можете изменить название включаемого файла, выбрав из меню View строку Resource Includes.

Листинг 2.15. Файл resource.h

// Включаемый файл, созданный Microsoft Developer Studio

// Используется в файле ресурсов MFDlgRes.rc

#define IDR_MENU 101

#define IDC_DEFAULT 1000

#define IDC_EDIT 1001

#define ID_TEST_DIALOG 40001

#define ID_TEST_EXIT 40002

// Следующие значения идентификаторов используются по

// умолчанию для новых объектов

#define _APS_NEXT_RESOURCE_VALUE 103

#define _APS_NEXT_COMMAND_VALUE 40003

#define _APS_NEXT_CONTROL_VALUE 1003

#define _APS_NEXT_SYMED_VALUE 101

Обратите внимание, что включаемый файл resource.h содержит не только определения идентификаторов, но также дополнительную служебную информацию. Она расположена после директивы #ifdef APSTUDIO_INVOKED и представляет собой ряд макроопределений. Данные макроопределения используются редактором ресурсов при создании новых идентификаторов.

Откройте страницу ClassView в окне Project Workspace. Обратите внимание, что если вы переместите окно Project Workspace к границе главного окна Visual C++, его заголовок пропадет и окно станет похоже на обычную панель управления. Если горизонтальный размер окна Project Workspace уменьшится, тогда исчезнут названия в закладках страниц и останутся только маленькие пиктограммы (рис. 2.31).

В ней отображаются два класса CMFDialogApp и CMyDialog. В главный класс приложения CMFDialogApp входит метод InitInstance. В класс CMyDialog входит конструктор CMyDialog, метод DoDataExchange , предназначенный для обмена данными между органами управления диалоговой панели и привязанных к ним переменных, а также методы OnOK , OnCancel и OnDefault. Последние три метода вызываются когда пользователь нажимает на кнопки OK, Cancel и Default, расположенные в диалоговой панели. Кроме того, определена глобальная переменная MFDialogApp.

Рис. 2.31. Классы проекта MFDialog

Страница ResourceView окна Project Workspace показывает все ресурсы, входящие в проект (рис. 2.32). В приложении MFDialog определен только один ресурс – диалоговая панель, имеющая идентификатор “DIALOGPANEL”.

Рис. 2.32. Ресурсы проекта MFDialog

Постройте проект и запустите полученный выполнимый файл. На экране появится диалоговая панель My Dialog, определенная в файле ресурсов нашего проекта (рис. 2.33). Вначале поле редактирования Line Editor пустое. В нем вы можете ввести любой текст. Если вы нажмете на кнопку Default, тогда все, что вы ввели в поле редактирования Line Editor, пропадает и в нем отображается строка Start Text.

Кроме кнопки Default в диалоговой панели My Dialog находятся еще две кнопки OK и Cancel. Если вы нажмете кнопку OK, тогда диалоговая панель закрывается, а на экране появляется текстовое сообщение, содержащее текст, введенный вами в поле Line Editor. Если нажать кнопку Cancel, то диалоговая панель My Dialog также закроется, но сообщение с введенным вами текстом не появится.

Рис. 2.33. Приложение MFDialog

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

Главный класс приложения

Теперь приступим к рассмотрению исходного текста приложения, представленного в листинге 1.1.

Сначала мы определяем главный класс приложения CMFDialogApp, наследованный от базового класса CWinApp . Класс CMFDialogApp и его методы используются аналогично приложению MFHello. Отличие заключается в том, что переопределенный метод InitInstance вместо отображения на экране сообщения при помощи функции AfxMessageBox , отображает полноценную модальную диалоговую панель.

// Метод InitInstance класса CMFDialogApp

// Создаем объект класса CMyDialog

// Отображаем на экране модельную диалоговую панель

// Отображаем на экране значение переменной m_Text,

// входящей в класс CMyDialog

Сначала создается объект dlgTest класса CMyDialog, который будет представлять диалоговую панель. Когда объект dlgTest создан, диалоговая панель еще не появляется на экране, для этого надо воспользоваться методом DoModal, определенным в классе CDialog.

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

Чтобы отобразить диалоговую панель на экране, мы вызываем для объекта dlgTest метод DoModal . На этом выполнение метода InitInstance приостанавливается, пока пользователь не закроет диалоговую панель.

Когда диалоговая панель закрыта, мы отображаем на экране состояние переменной dlgTest.m_Text, которая соответствует полю ввода Edit диалоговой панели. Последний оператор метода return возвращает значение FALSE и приложение завершается.

Класс диалоговой панели

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

// Класс CMyDialog – класс диалоговой панели

class CMyDialog : public CDialog <

virtual void DoDataExchange(CDataExchange* pDX);

// Обработчики сообщений от кнопок диалоговой панели

afx_msg void OnDefault();

virtual void OnCancel();

virtual void OnOK();

Обратите внимание на то, как мы определяем конструктор класса CMyDialog. После названия конструктора стоит символ двоеточие и название конструктора класса CDialog. При этом в качестве параметра, конструктору CDialog передается идентификатор диалоговой панели «DIALOGPANEL»:

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

// Инициализируем переменную m_Text

Основное назначение конструктора CMyDialog – вызвать конструктор класса CDialog, указав ему в качестве параметра идентификатор диалоговой панели «DIALOGPANEL». Именно конструктор класса CDialog выполняет создание диалоговой панели.

В конструкторе также инициализируется переменная m_Text, входящая в класс CMyDialog. В нее записывается пустая строка.

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

Механизм автоматического обмена данными позволяет привязать к органам управления диалоговой панели переменные или элементы данных класса диалоговой панели. Ряд специальных функций, определенных в библиотеке MFC, вызываются методом DoDataExchange и выполняют обмен данными между органами управления диалоговой панели и соответствующими элементами данных класса диалоговой панели. Такой обмен работает в обоих направлениях. Информация из органов управления диалоговой панели может записываться в элементы данных класса, или в обратном направлении – информация из элементов данных класса может отображаться в диалоговой панели.

Названия всех функций, обеспечивающих обмен данными, начинаются символами DDX_. Например определены функции DDX_Text, DDX_Radio, DDX_Check, DDX_Scroll и т. д. Практически каждый тип органов управления диалоговой панели имеет собственную функцию для выполнения процедуры обмена данными.

Все функции DDX_ имеют три параметра. Первый параметр содержит указатель на объект класса CDataExchange. Этот объект определяет параметры обмена, в том числе направление, в котором надо выполнить обмен данными. Второй параметр определяет идентификатор органа управления, с которым выполняется обмен данными. Третий параметр содержит ссылку на элемент данные класса диалоговой панели, связанный с данным органом управления.

Ниже представлен прототип функции DDX_, предназначенной для обмена информацией между полем редактирования диалоговой панели и элементом данных, входящим в класс диалоговой панели. Этот элемент имеет класс CString:

void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value);

Метод DoDataExchange позволяет выполнять проверку данных, которые пользователь вводит в диалоговой панели. Для этого предназначен ряд функций DDV_. Эти функции позволяют гарантировать, что данные, введенные пользователем в диалоговой панели, соответствуют определенным условиям.

Если вы используете функцию DDV_ для проверки ввода в данном органе управления, вы должны вызвать ее сразу после вызова функции DDX_ для этого же органа управления.

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

В отличие от функций DDX_, функции DDV_, в зависимости от их предназначения, имеют различное количество параметров. Первый параметр, как и в случае функций DDX_, содержит указатель на объект класса CDataExchange . Остальные параметры имеют различное назначение в зависимости от функции. Так, например, прототип функции, которая проверяет максимальную длину введенной текстовой строки, выглядит следующим образом:

void AFXAPI DDV_MaxChars(CDataExchange* pDX, CString const& value, int nChars);

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

Другие функции DDV_ имеют больше параметров. Так, функция DDV_MinMaxInt, проверяющая, что введенное значение находится в определенных границах, имеет 4 параметра:

void AFXAPI DDV_MinMaxInt(CDataExchange* pDX, int value, int minVal, int maxVal);

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

Приложение не должно напрямую вызывать метод DoDataExchange. Он вызывается через метод UpdateData, определенный в классе CWnd (рис. 2.34). Если вам надо выполнить обмен данными, между органами управления и элементами данных класса диалоговой панели, используйте метод UpdateData . Приведем прототип метода UpdateData:

BOOL UpdateData(BOOL bSaveAndVal >

Рис. 2.34. Вызов метода DoDataExchange

Необязательный параметр bSaveAndValidate, определяет, как будет происходить обмен данными. Если метод UpdateData вызывается с параметром FALSE, выполняется инициализация диалоговой панели. Информация из элементов данных класса отображается в органах управления диалоговой панели.

В случае, если метод UpdateData вызван с параметром TRUE, данные перемещаются в обратном направлении. Из органов управления диалоговой панели они копируются в соответствующие элементы данных класса диалоговой панели.

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

При создании модальной диалоговой панели перед тем как панель появится на экране, вызывается виртуальный метод OnInitDialog класса CDialog . По умолчанию OnInitDialog вызывает метод UpdateData и выполняет инициализацию органов управления. Если вы переопределили метод OnInitDialog в своем классе диалоговой панели, в первую очередь вызовите метод OnInitDialog класса CDialog.

Метод UpdateData также вызывается некоторыми другими методами класса CDialog. Так, метод UpdateData вызывается, когда пользователь закрывает модальную диалоговую панель, нажимая кнопку OK. Заметим, что кнопка OK должна иметь идентификатор IDOK. Если пользователь нажмет на кнопку Cancel, имеющую идентификатор IDCANCEL, то диалоговая панель также закрывается, но метод UpdateData не вызывается и обмен данными не происходит.

// Метод DoDataExchange класса CMyDialog

void CMyDialog::DoDataExchange(CDataExchange* pDX) <

DDX_Text(pDX, IDC_EDIT, m_Text);

Методу DoDataExchange передается указатель pDX на объект класса CDataExchange. Этот объект создается, когда вы инициируете процесс обмена данными, вызывая метод UpdateData . Элементы данных класса CDataExchange определяют процедуру обмена данными, в том числе определяют, в каком направлении будет происходить этот обмен. Обратите внимание, что указатель pDX передается функциям DDX_ и DDV_.

В библиотеку MFC входит большое количество функций DDX_ и DDV_. Чтобы облегчить задачу написания метода DoDataExchange для класса вашей диалоговой панели, используйте ClassWizard. Он позволяет привязать к органам диалоговой панели элементы данных класса. При этом метод DoDataExchange создается ClassWizard автоматически. ClassWizard сам выбирает, какие функции DDX_ и DDV_ надо использовать для данного органа управления и связанного с ним элемента данных класса диалоговой панели. Подробно об использовании ClassWizard для разработки диалоговых панелей вы можете прочитать в главе “Приложение с главной диалоговой панелью”.

Класс диалоговой панели должен обрабатывать сообщения от своих органов управления, поэтому он должен иметь таблицу сообщений. В заголовке таблицы сообщений указывается имя класса CMyDialog и имя базового класса CDialog:

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

Таблица сообщений содержит только одну строку, в которой обрабатывается сообщение с кодом извещения ON_BN_CLICKED от кнопки “Default”. Когда пользователь нажимает кнопку, вырабатывается данное сообщение и вызывается его обработчик – метод OnDefault, определенный в классе CMyDialog:

// Метод OnDefault класса CMyDialog

m_Text = «Start Text»;

Две другие кнопки диалоговой панели «DIALOGPANEL», OK и Cancel не представлены в таблице сообщений, но тем не менее в приложении определены методы OnOK и OnCancel, которые вызываются при нажатии на них. Оказывается для диалоговых панелей определены две стандартные кнопки OK и Cancel, которым присвоены специальные идентификаторы IDOK и IDCANCEL.

Базовый класс CDialog, также как и класс CMyDialog, содержит таблицу сообщений. Если вы установили библиотеку MFC вместе с исходными текстами, вы можете изучить реализацию класса CDialog в файле Dlgcore.cpp. Сам класс CDialog определен во включаемом файле Afxwin.h. Ниже представлена выдержка из таблицы сообщений, определенной в файле Dlgcore.cpp:

Среди прочих сообщений, в этой таблице определены командные сообщения с идентификаторами IDOK и IDCANCEL. Для обработки этих командных сообщений определены виртуальные методы OnOK и OnCancel. Данные методы также определены в MFC (файл Dlgcore.cpp). Поэтому когда диалоговая панель содержит кнопки с идентификаторами IDOK и IDCANCEL, как правило нет необходимости создавать для них обработчики.

Так как в таблице сообщений класса CMyDialog отсутствуют макрокоманды для обработки сообщений от кнопок OK и Cancel, они передаются для обработки базовому классу CDialog. Здесь они обрабатываются виртуальными методами OnOK и OnCancel.

Метод OnOK, определенный в классе CDialog, копирует данные из полей диалоговой панели в связанные с ними переменные. Для этого вызывается метод UpdateData с параметром TRUE. Затем выполняется вызов метода EndDialog, который закрывает диалоговую панель и возвращает значение IDOK. После того как диалоговая панель закрыта, метод DoModal возвращает значение IDOK и продолжает работать метод InitInstance.

// В процессе обмена данными произошла ошибка

TRACE0(«UpdateData failed during dialog termination.\n»);

Метод OnCancel, определенный в классе CDialog, еще проще, чем OnOK. Он только закрывает диалоговую панель и возвращает значение IDCANCEL. Копирование данных из полей диалоговой панели не происходит, так как пользователь отменил изменения, нажав кнопку Cancel.

Так как методы OnOK и OnCancel определены в классе CDialog как виртуальные, вы можете переназначить их в своем классе CMyDialog. В этом случае управление получат переопределенные вами методы, а не методы класса CDialog. Методы базового класса CDialog можно вызвать, явно указав класс.

// Метод OnCancel класса CMyDialog

// Подаем звуковой сигнал

// Вызываем метод OnCancel базового класса

Переопределенный нами метод OnCancel вызывает функцию программного интерфейса MessageBeep, которая подает звуковой сигнал, а затем вызываем метод OnCancel базового класса CDialog. Метод OnCancel базового класса CDialog вызывается в конце, так как он закрывает саму диалоговую панель.

Аналогично методу OnCancel мы переопределили метод OnOK.

// Метод OnOK класса CMyDialog

// Вызываем метод OnOK базового класса

// Подаем звуковой сигнал

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

Приложение с немодальной диалоговой панелью

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

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

Следующие шаги выполняются только для немодальных диалоговых панелей. Для класса диалоговой панели надо определить конструктор, объявив его как public. Чтобы открыть немодальную диалоговую панель, создайте объект класса диалоговой панели, обратившись к определенному вами конструктору. В этот момент диалоговая панель еще не появляется на экране. Для этого надо вызвать метод Create класса CDialog.

Вы можете вызывать метод Create либо непосредственно из конструктора класса диалоговой панели, либо уже после создания объекта. Если диалоговая панель имеет стиль WS_VISIBLE, она сразу появится на экране. В противном случае для этого надо вызвать метод ShowWindow. Как видите, для отображения немодальной диалоговой панели мы не использовали метод DoModal.

В классе CDialog определены два прототипа метода Create. Один позволяет указать диалоговую панель через ее текстовое имя, а другой через числовой идентификатор:

BOOL Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);

BOOL Create(UINT n >

Параметр lpszTemplateName должен содержать указатель на строку, закрытую нулем, содержащую имя ресурса диалоговой панели. Если вы используете метод Create, имеющий второй прототип, вместо имени шаблона, надо указать в параметре nIDTemplate его идентификатор.

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

Метод Create возвращает управление сразу после того, как диалоговая панель отобразилась на экране. Он возвращает ненулевое значение, если создание диалоговой панели завершилось успешно и нуль в противном случае.

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

Теперь вам остается удалить объект, управляющий диалоговой панелью. Для этого в классе диалоговой панели можно переопределить виртуальный метод PostNcDestroy (этот метод первоначально определен в базовом классе CWnd). В нем вы можете вызвать оператор delete, передав ему в качестве параметра указатель на данный объект this .

Глава 1. Знакомьтесь — библиотека классов MFC

Знакомьтесь — библиотека классов MFC

Чего не понимают, тем не владеют.

Иоганн Вольфганг Гете

Для того чтобы выполнять какую-либо работу на профессиональном уровне, недостаточно поверхностного знакомства с тем инструментарием, которым собираешься пользоваться. Необходимо совершенно четко и ясно представлять себе внутреннюю структуру и логику работы используемого средства. В полной мере это относится и к широко применяемой в настоящее время для построения (создания) программных продуктов библиотеке классов MFC (Microsoft Foundation Class). K MFC следует подходить именно как к инструменту, который, принимая на себя большую часть черновой работы, требует от нас не просто знакомства с ним, но и глубокого изучения. Только знание всех нюансов построения и возможностей этой библиотеки позволит нам быстро и легко создавать программы любой степени сложности. В противном случае никогда не будет уверенности, что созданное приложение при любых условиях работает правильно — слишком много скрыто от программиста. Функции вызываются не только из недр Windows, но и из недр библиотеки. Ни о каком последовательном вызове функций речь не идет. Данные готовятся неизвестно где и неизвестно кем и когда обрабатываются. Так что какая уж тут уверенность.

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

Перед создателями библиотеки стояла задача создания объектно-ориентированного интерфейса для Windows, удовлетворяющего следующим основным целям проектирования программных продуктов:

  • сокращение усилий по программированию приложений для Windows;
  • скорость выполнения программ, написанных с использованием библиотеки, должна быть сопоставима с программами, написанными на языке С с использованием Win32 API;
  • минимальный размер вспомогательного кода;
  • способность напрямую вызывать любую С-функцию Win32 API;
  • легкость использования Win32 API в C++ должна быть такая же, как и при использовании традиционного С.

Надо сказать, что поставленная задача была решена на очень высоком уровне. Созданная библиотека классов охватывает все компоненты Windows — окна, блоки диалога, контексты устройств, общие объекты GDI (битовые образы и кисти), элементы управления и многие другие стандартные элементы. Суть программирования под Windows — обработка событий — предоставлена программистам в удобном и привычном виде. Классы библиотеки полностью вобрали в себя многочисленные операторы switch , которые так загромождают программы, написанные на языке С. Наряду с этим вы можете совершенно свободно смешивать вызовы библиотеки классов с прямыми вызовами Win32 API. Кроме того, за сравнительно небольшой промежуток времени корпорацией Microsoft было разработано несколько версий библиотеки MFC, которые становились все мощнее и удобнее. Вместе с Visual C++ 6.0 поставляется версия 4.23 библиотеки, и есть все основания считать, что ее развитие будет продолжено. К тому же поддержка библиотеки MFC компиляторами и средствами разработки ПО, созданными другими компаниями, позволяет сконцентрироваться именно на ней. Но давайте рассмотрим все по порядку. Начнем с макросов, глобальных функций и переменных, которые, хотя и не входят непосредственно в библиотеку, очень тесно с ней связаны и значительно облегчают программирование, а затем перейдем к общему обзору библиотеки.

Макросы, глобальные функции и переменные

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

Все макросы, глобальные функции и переменные можно разбить на несколько категорий: основные, работа с базами данных, работа в Internet, OLE и элементы управления OLE . Поскольку в данной книге мы не будем подробно рассматривать работу с базами данных, в сети и с использованием OLE (этим вопросам будут посвящены следующие книги), то ограничимся изучением только основных макросов, глобальных функций и переменных. Начнем, естественно, с начала. Практически все глобальные функции начинаются с префикса » Afx «. Исключение составляют большинство функций для работы с базами данных и функции, обеспечивающие обмен данными. Для всех без исключения глобальных переменных применяется префикс » Afx «, а все макросы записываются заглавными буквами.

Большинство типов данных полностью соответствуют представленным в SDK, однако есть типы, специфичные только для MFC.

Основы программирования на Visual C++

Библиотеки в C++

Библиотеки предоставляют программисту возможность использовать при разработке программы готовые фрагменты кода. В библиотеки могут быть включены подпрограммы, структуры данных, классы, макросы. Для языка C++ разработано много библиотек различного назначения. Некоторые библиотеки используются по умолчанию, их подключение к проекту осуществляется автоматически (библиотека времени выполнения — RTL, Runtime Library). Другие библиотеки можно использовать по требованию (в консольном приложении VC++ — библиотека MFC), для этого следует подключить директивой include их заголовки и/или сделать соответствующие настройки проекта. Файлы, содержащие библиотеки, имеют расширение *. lib (статическая) и *. dll (динамическая).

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

Библиотека MFC

Библиотека MFC (Microsoft Foundation Classes) — фундаментальная библиотека классов фирмы Microsoft. MFC используется для создания объектно-ориентированных приложений под Windows в среде Visual C++, Borland C++ 5.0, C++ Builder. Предшественницей MFC была библиотека Application Framework (AFX), выпущенная в виде отдельного программного продукта (1992). MFC создает готовый каркас приложения, который дополняется в соответствии с поставленной задачей. Библиотека содержит определения классов C++, реализующих интерфейс с Windows, на основе которых могут быть определены классы пользователя. Для большинства классов MFC базовым определен класс CObject. Производные от него классы представляют собой различного вида окна (например, CFrameWnd — класс окна с рамкой), диалоговые панели (класс CDialog), контексты устройств (класс CDC), графические компоненты (класс CPen — перо). Также в состав библиотеки MFC включены средства для работы со строками, файлами. [1]

Классы в C++

Поскольку C++ — объектно-ориентированный язык, он позволяет использовать при разработке программ как готовые классы, доступные через соответствующие библиотеки, так и классы, разработанные пользователем.

Объявление класса начинается с ключевого слова class. Переменные, константы, функции, включенные в класс, называются членами класса. Члены класса объявляются в одном из трех разделов класса: public, private, protected. Включение члена класса в тот или иной раздел влияет на доступность этого члена для объектов других классов.

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

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

visual программирование приложение

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

Рассмотрим в качестве примера класс принтеров. Включим в его состав следующие свойства: модель, год выпуска и состояние принтера; спрячем эти свойства от постороннего воздействия, поместив в раздел private. Ограничимся двумя возможными состояниями принтера: 0 — принтер готов к работе, 1 — принтер печатает. Методы сделаем доступными для других объектов. Метод init_printer () позволит установить начальные значения свойствам принтера. Метод set_print () переведет принтер в состояние печати, если принтер до того находился в состоянии готовности, и не изменит его состояния, если принтер уже печатал. Метод stop_print () приводит к остановке печати. Метод show () отображает состояние принтера на экране:

Замечание. Если раздел private включен в объявлении класса первым, ключевое слово private можно опустить:

В главную часть программы — функцию main () — включим следующие действия: создание объекта, инициализация свойств объекта, изменение состояния объекта и вывод его текущего состояния на экран. [1]

Лекция 4. Обзор библиотеки MFC

Назначение библиотеки MFC

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

MFC содержит около 200 классов, представляющих практически все необходимое для написания Windows-приложений: от окон до элементов управления ActiveX. Одни классы можно использовать непосредственно, а другие – в качестве базовых для создания новых классов. Некоторые классы MFC очень просты, например, класс CPoint для хранения двумерных координат точки. Другие классы являются более сложными, например, класс CWnd инкапсулирует функциональность окна Windows. В приложении MFC напрямую вызывать функции Windows API приходится редко. Вместо этого программист создает объекты классов MFC и вызывает их функции-члены. В MFC определены сотни функций-членов, которые служат оболочкой функций API, и часто их имена совпадают с именами соответствующих функций API. Например, для изменения местоположения окна в API есть функция SetWindowPos. В MFC это действие выполняется с помощью функции-члена CWnd::SetWindowPos.

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

В каркасе приложения MFC есть понятия высокого уровня, которых нет в Windows API. Например, архитектура «документ/вид» является мощной инфраструктурой, надстроенной над API и позволяющей отделить данные программы от их графического представления. Эта архитектура отсутствует в API и полностью реализована в каркасе приложения с помощью классов MFC.

1.1 Преимущества использования Си++/MFC по сравнению с Си/Windows API

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

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

Применительно к программированию для Windows можно сказать, что без готовой библиотеки классов ООП дает весьма незначительное уменьшение количества исходного текста, который должен написать программист. Основные преимущества ООП проявляются при использовании библиотеки классов – т.е. набора повторно используемых компонент. Эти компоненты облегчают решение типичных задач, например, для добавления в приложение MFC стыкуемой панели инструментов можно использовать класс CToolBar, которому надо только указать параметры кнопок панели. Использовать сложные технологии Windows, например, технологии ActiveX (в том числе COM и OLE) без готовых классов практически невозможно.

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

Основные задачи проектирования MFC

При проектировании MFC перед разработчиками Microsoft стояли две основных задачи:

1) MFC должна служить объектно-ориентированным интерфейсом для доступа к API операционных систем семейства Windows с помощью повторно используемых компонент – классов.

2) накладные расходы по времени вычислений и по объему памяти при использовании MFC должны быть минимальны.

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

Уменьшение накладных расходов на библиотеку MFC было достигнуто за счет решений, определяющих способ реализации классов MFC – о том, как именно объекты ОС будут оформлены в виде классов. Одно из этих решений – способ связи между объектами MFC и объектами Windows. В Windows информация о свойствах и текущем состоянии окна хранится в служебной памяти, принадлежащей ОС. Эта информация скрыта от приложений, которые работают с окнами исключительно посредством дескрипторов (переменных типа HWND). В MFC «оболочкой» окна является класс CWnd. Но в нем нет переменных-членов, дублирующих все свойства окна с заданным HWND. В классе CWnd хранится только дескриптор окна. Для этого заведена открытая переменная-член CWnd::m_hWnd типа HWND. Когда программист запрашивает у объекта CWnd какое-нибудь свойство окна (напр., заголовок), то этот объект вызывает соответствующую функцию API, а затем возвращает полученный результат.

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

1.3 Архитектура «документ/вид»

В устройстве каркаса приложения MFC важнейшую роль играет архитектура «документ/вид». Это такой способ проектирования приложения, когда в нем отдельно создаются объекты-документы, ответственные за хранение данных приложения, и объекты-виды, ответственные за отображение этих данных различными способами. Базовыми классами для документов и видов в MFC служат классы CDocument и CView. Классы каркаса приложения CWinApp, CFrameWnd и др. работают совместно с CDocument и CView, чтобы обеспечить функционирование приложения в целом. Сейчас пока рано обсуждать детали архитектуры «документ/вид», но вы должны, как минимум, знать термин «документ/вид», часто упоминаемый при рассмотрении MFC.

Приложения MFC можно писать и без использования документов и видов (например, при изучении основ MFC). Но доступ к большинству возможностей каркаса возможен только при поддержке архитектурs «документ/вид». В действительности это не является жестким ограничением структуры приложения, и большинство программ, обрабатывающих документы какого-либо типа, могут быть преобразованы в эту архитектуру. Не следует думать (по аналогии с термином «документ»), что эта архитектура полезна только для написания текстовых редакторов и электронных таблиц. «Документ» – это абстрактное представление данных программы в памяти компьютера. Например, документ может быть просто массивом байт для хранения игрового поля компьютерной игры, или он действительно может быть электронной таблицей.

Какие именно преимущества получают в MFC приложения «документ/вид»? В частности, это значительное упрощение печати и предварительного просмотра, готовый механизм сохранения и чтения документов с диска, преобразование приложений в серверы документов ActiveX (приложения, документы которых можно открывать в Internet Explorer). Подробно архитектура документ/вид будет рассмотрена позже.

Иерархия классов MFC

Большинство классов MFC явно или неявно унаследованы от класса CObject. Класс CObject обеспечивает для своих подклассов три важных возможности:

· сериализация (запись или чтение данных объекта на диск);

· средства динамического получения информации о классе;

· диагностическая и отладочная поддержка.

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

Динамическая информация о классе (Run-time class information, RTCI) позволяет получить во время выполнения программы название класса и некоторую другую информацию об объекте. Механизм RTCI реализован независимо от механизма динамической идентификации типа (RTTI), встроенного в Си++. Во многом эти средства похожи, но RTCI был разработан на несколько лет раньше.

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

CObject предоставляет подклассам еще ряд полезных возможностей. Например, для защиты от утечек памяти в отладочном режиме в классе перегружены операторы new и delete. Если вы динамически создали объект подкласса CObject, и забыли удалить его до завершения программы, то MFC выдаст в отладочное окно Visual C++ предупреждающее сообщение.

Последнее изменение этой страницы: 2020-08-01; Нарушение авторского права страницы

Введение в Visual C++. MFC

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

Вероятно, что лучшей интегрированной средой разработки приложений под Windows, является Microsoft Visual C++. Именно этой программой мы и будем пользоваться в дальнейшим. Установочный образ Вы можете скачать на сайте разработчика , впрочем, думаю у вас не возникнет проблем с этой фундаментальной задачей.

Компания Microsoft разработала мощный инструмент для разработки сложных приложений — MFC. MFC (Microsoft Foundation Classes) — библиотека классов языка C++, предназначенная для создания визуальных приложений при помощи встроенных средств. MFC поддерживает современные технологии программирования, благодаря чему программы написанные с ее помощью будут обладать необходимой функциональностью и надежностью. Благодаря ей программист получает шаблонный «скелет» программы, после чего ему остается вписать код в необходимые места.

Итак, теперь стоит поговорить о более грустных вещах. Библиотека MFC достаточно сложна, так как во всю использует возможности языка C++. А это значит, что в «арсенале» начинающего изучать визуальное программирование используя этот «дар» от Microsoft должны присутствовать навыки написания кода на C++. В частности было бы неплохо изучить: рекурсию и перегрузку функций, основы классов, перегрузку операций и наследование. Но для самых отчаянных (тех кто не боится не разобраться что к чему), думаю возможно дуализировать задачи, то есть одновременно изучать как библиотеку MFC, так и базовые понятия C++.

Что касается самой Visual C++, то тут стоит добавить, что эта среда разработки обычно входит в линейку программ под общим названием Visual Studio, но вполне реально приобрести ее в отдельном экземпляре.

Разработка пользовательского интерфейса

Специальность: Прикладная информатика

Целью освоения дисциплины (модуля) «Разработка пользовательского интерфейса» является ознакомление студентов с ООП к разработке приложений для ОС Windows, а именно программированию с использованием библиотеки MFC (Microsoft Foundation Classes), а также расширяются и углубляются знания студентов в области структуры фундаментальных механизмов ОС Windows и создания программ для нее. Кроме того, в рамках курса даются практические навыки работы в среде MS Visual Studio при создании приложений на языке программирования C++.

Программа курса требует от студентов знаний основ объектно-ориентированного программирования.

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

В результате освоения дисциплины обучающийся должен:

Знать: основные принципы и механизмы функционирования ОС Windows, с точки зрения разработчиков программных продуктов для этой ОС. Структуру, основные понятия и принципы использования библиотеки MFC. Иметь представление об особенностях этой библиотеки по отношению к традиционным методам программирования для Windows.

Уметь: Ориентироваться в средствах, предоставляемых данной библиотекой, и уметь выбирать наиболее эффективные из них для решения конкретных задач..

Владеть: представлениями (навыками) ООП к разработке приложений для ОС Windows и реализации данного подхода на языке программирования C++.

Содержание

1. ФУНКЦИОНИРОВАНИЕ ОС WINDOW. Пользовательский интерфейс ОС. Система, управляемая сообщениями. Интерфейс прикладного программирования. Управление графическим выводом.

2. СТРУКТУРА ПРИЛОЖЕНИЯ ДЛЯ WINDOWS. Стандартный цикл обработки сообщений. Оконная процедура. Основные типы оконных сообщений.

3. ОБЗОР БИБЛИОТЕКИ КЛАССОВ MFC. Иерархия классов MFC. Классы, определяющие архитектуру приложения. Окна, блоки диалога и элементы управления. Классы для вывода на экран. Макросы, глобальные функции и переменные.

4. ОСНОВНЫЕ СОСТАВЛЯЮЩИЕ ПОЛЬЗОВАТЕЛЬСКОГО ПРИЛОЖЕНИЯ НА БАЗЕ MFC. Соглашения об именах MFC. Включаемые файлы. Функция WinMain. Минимальная программа для Windows. Регистрация класса окна и создание окна.

5. ОБРАБОТКА СООБЩЕНИЙ В MFC. Цикл обработки сообщений. Категории сообщений. Карта сообщений. Стандартный маршрут команды. Функции для работы с сообщениями.

6. БЛОКИ ДИАЛОГА. Модальные и немодальные блоки диалога. Стандартные блоки диалога.

7. ЭЛЕМЕНТЫ ИНТЕРФЕЙСА ПОЛЬЗОВАТЕЛЯ. Общие элементы управления. Панели элементов управления. Меню. Создание элементов управления. Классы стандартных элементов управления.

8. ГРАФИЧЕСКИЙ ИНТЕРФЕЙС УСТРОЙСТВ (GDI). Классы графического интерфейса. Классы контекстов устройств. Классы графических объектов.

9. АРХИТЕКТУРА «ДОКУМЕНТ/ПРЕДСТАВЛЕНИЕ». Основные положения. Документ и его представления.

10. СОЗДАНИЕ SDI И MDI ПРИЛОЖЕНИЙ НА БАЗЕ MFC. Окна, определенные в ОС Windows. Создание окна и библиотека MFC. Ограничение доступа к окну. Классы CWnd, CFrameWnd, CMDIFrameWnd, CMDIChildWnd.

Лабораторный практикум

  1. Блоки диалога.
  2. Элементы интерфейса пользователя.
  3. Графический интерфейс устройств (GDI).
  4. Создание SDI и MDI приложений на базе MFC.

Литература

а) основная литература:

  1. Баженова И.Ю. Visual C++ 6.0 (VISUAL STUDIO 98). Уроки программирования. — М.: Диалог МИФИ, 2001 – 416 с.
  2. Мешков А.В., Тихомиров Ю.В. Visual C++ и MFC: Пер. с англ. – 2-е изд. перераб. и доп. — СПб.: БХВ-Петербург, 2002. – 1040 с.: ил.

б) дополнительная литература:

  1. Николенко Д.В. Самоучитель по Visual C++ 6. – СПб.: Наука и техника, 2001. – 367 с.
Илон Маск рекомендует:  Begin declare section
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL