- •История Windows
- •Windows 1.0
- •Windows 1.3
- •Windows 2.0
- •Windows 3.0
- •Windows 3.1
- •Windows for Workgroups версии 3.11
- •Windows NT
- •Windows 95
- •Windows NT Workstation 4.0 и Windows NT Server 4.0
- •Windows NT 4.0 Server Enterprise Edition
- •Windows 98
- •Windows 98 Second Edition (SE)
- •Windows 2000
- •Windows 98 Millenium Edition (ME)
- •Windows XP
- •Общая архитектура WINDOWS приложения.
- •Каркас приложения
- •Регистрация класса окна
- •Создание окна.
- •Отображение окна.
- •Цикл обработки очереди сообщений.
- •WndProc
- •Обработка сообщений типового приложения.
- •Контрольные вопросы
- •Сообщения
- •Типы сообщений
- •Обработка клавиатурных сообщений
- •Обработка сообщений от мыши
- •Сообщения таймера
- •Контрольные вопросы
- •Организация ввода
- •Разупорядоченный ввод
- •Разделение потоками виртуальных очередей ввода
- •Локальное состояние ввода
- •Ввод с клавиатуры и фокус
- •Управление курсором мыши
- •Контрольные вопросы
- •Окна
- •Окна Windows
- •Иерархия окон
- •Оконная процедура, стандартные оконные процедуры
- •Стиль класса окна
- •Стили окон, окна основных стилей
- •Перекрывающиеся окна
- •Временные окна
- •Дочерние окна
- •Сообщения управления окнами
- •Окна с полосами прокрутки
- •Системные метрики
- •Определение размера окна
- •Определение расположения окна
- •Контрольные вопросы
- •Графический интерфейс устройств(GDI).
- •Создание (получение) контекста устройств.
- •Сохранение контекста устройства.
- •Прямые (отрезки) и кривые
- •Закрашенные области
- •Битовые шаблоны (растровые шаблоны, растровые образы)
- •Текст и шрифты
- •Режимы масштабирования и преобразования
- •Метафайл
- •Регионы
- •Путь
- •Палитры
- •Контрольные вопросы
- •Объекты ядра
- •Что такое объект ядра
- •Учет пользователей объектов ядра
- •Защита
- •Таблица описателей объектов ядра
- •Создание объекта ядра
- •Закрытие объекта ядра
- •Синхронизация объектов
- •Именованные объекты
- •Дублирование описателей объектов
- •Изменение флагов описателя
- •Синхронизация потоков
- •Критическая секция
- •Мьютексы
- •Семафоры
- •События
- •Ожидаемые таймеры
- •Контрольные вопросы
- •Ресурсы Windows приложения
- •Файлы ресурсов приложения
- •Значки (пиктограммы)
- •Курсоры
- •Битовые образы
- •Символьные строки
- •Ресурсы, определяемые пользователем
- •Таблица акселераторов
- •Меню
- •Диалоговые окна
- •Контрольные вопросы
- •Элементы управления
- •Дочерние окна управления
- •Создание дочерних окон
- •Сообщения дочерних окон родительскому окну
- •Сообщения родительского окна дочерним окнам
- •Дочерние окна и фокус ввода
- •Дочерние окна управления и цвет
- •Кнопки различных стилей (класс BUTTON)
- •Нажимаемые кнопки
- •Флажки-переключатели
- •Переключатели
- •Окна групп
- •Кнопки, определяемые пользователем
- •Статические поля (класс static)
- •Текстовые редакторы (класс edit)
- •Списки разных стилей (класс listbox)
- •Комбинированные списки (класс combobox)
- •Полосы прокрутки (класс scrollbar)
- •Контрольные вопросы
- •Расширенные элементы управления
- •Основы общих элементов управления
- •Инициализация библиотеки элементов общего пользования
- •Создание элементов управления общего пользования
- •Посылка сообщений общим элементам управления
- •Уведомляющие сообщения от общих элементов управления
- •Контрольные вопросы
- •Стандартные диалоговые окна.
- •Окна сообщений
- •Диалоговые окна общего пользования
- •Контрольные вопросы
- •Динамически подключаемые библиотеки
- •Создание DLL
- •Проецирование DLL на адресное пространство процесса
- •Функция входа/выхода
- •Функция DllMain и стандартная библиотека С
- •Функция LibEntry
- •Функция LibMain
- •Функция WEP
- •Экспорт функций и переменных из DLL
- •Импорт функций и переменных из DLL
- •Заголовочный файл DLL
- •Разделы в ЕХЕ- и DLL-файлах
- •Контрольные вопросы
- •Файлы, проецируемые в память
- •Контрольные вопросы
- •Классы, определяющие архитектуру приложения
- •Классы приложения и поддержки потоков
- •Классы приложения и потоков
- •Классы фреймов окон
- •Получение информации о приложении
- •Соглашения об именах MFC
- •Включаемые файлы
- •Функция WinMain
- •Класс CWinApp
- •Класс CWnd
- •Класс CFrameWnd
- •Создание главного окна SDI-приложения
- •Примечание
- •Создание главного окна SDI-приложения
- •Создание дочерних окон
- •Ограничение размеров окна
- •Ограничение доступа к окну
- •Создание многодокументных приложений
- •Класс CMDIChildWnd
- •MDI — пример приложения
- •Категории сообщений
- •Карта сообщений
- •Компоненты карты сообщений
- •Класс CCmdTarget
- •Стандартный маршрут команды
- •Команды обновления и класс CCmdlll
- •Функции для работы с сообщениями
- •Основные положения
- •Класс CDocTemplate
- •Класс CSingleDocTemplate
- •Роль фреймов в архитектуре "документ/представление"
- •Документ и его представления
- •Документы
- •Класс CDocument
- •Класс CArchive
- •Представления
- •Класс CView
- •Панели элементов управления
- •Класс CStatusBar
- •Класс CStatusBarCtrl
- •Класс CDialogBar
- •ControlBars — пример приложения
- •НЕКОТОРЫЕ КЛАССЫ MFC
- •Класс CObject - основной класс MFC
- •Конструкторы класса
- •Оператор присваивания
- •Диагностика
- •Проверка целостности объектов класса
- •Получение дампа объекта класса
- •Сохранение и восстановление состояния объекта
- •Метод IsSerializable
- •Виртуальный метод Serialize
- •Информация о классе
- •Виртуальный метод GetRuntimeClass
- •Метод IsKindOf
- •Класс CPoint - точка на плоскости
- •Класс CSize - относительные координаты
- •Класс CString - текстовые строки
- •Конструктор класса
- •Коллекции
- •Массивы - шаблон CArray
- •Списки - шаблон CList
- •Словари - шаблон CMap
- •Класс CTime - дата и время
- •Файловая система - класс CFile
- •Открытие и создание файлов
- •Идентификатор открытого файла
- •Закрытие файлов
- •Чтение и запись файлов
- •Метод Flush
- •Операции с файлами
- •Блокировка
- •Позиционирование
- •Характеристики открытого файла
- •Файловая система - классы CMemFile и CStdioFile
- •Модификация класса CMemFile
- •Файловая система - класс CStdioFile
- •Запись и восстановление объектов
- •Запись в архивный файл
- •Чтение из архивного файла
- •Исключения - класс CException
- •Класс CException
- •Класс CMemoryException
- •Класс CFileException
- •Приложение Except
- •Класс CArchiveException
- •Класс CNotSupportedException
- •Класс CResourceException
- •Класс CUserException
Основные положения
Прежде, чем переходить к рассмотрению темы, вынесенной в заголовок части, сделаем обзор тех основных возможностей, которыми уже можно осознанно пользоваться.
Каждое приложение, написанное для Windows, имеет одно главное окно, которое состоит из двух компонентов
— фрейма и клиентской (рабочей) области. Оно может быть как стандартным окном Windows (например, при построении SDI- и MDI-приложений), так и обычным блоком диалога. В любом случае, внутри главного окна, приложение предоставляет пользователю всю необходимую для работы информацию, под которой понимаются не только данные, т. е. текст, рисунки и т. п., но и элементы интерфейса — меню, полосы прокрутки, панели инструментов, строка состояния и т. д. Каждый из этих элементов (по крайней мере, для приложений, созданных с использованием библиотеки классов MFC) является объектом, в состав которого входят функции, определяющие его поведение — взаимодействие как с другими объектами, так и с данными, с которыми он работает. Любые действия пользователя во время выполнения приложения вызывают генерацию сообщений, которые содержат в себе информацию о том, что конкретно сделал пользователь. Все объекты приложения обладают способностью реагировать на те или иные сообщения. Во многих случаях эта способность заложена в библиотеке классов MFC, а для других реализуются специальные обработчики. Повторим — все перечисленные свойства характерны (с той или иной степенью полноты) для каждого Windows-приложения.
Оставим в стороне приложения, базирующиеся на блоках диалога, и сосредоточимся на тех, которые в качестве своего главного окна имеют стандартное окно Windows. Основным для таких окон является объект, созданный на базе класса CFrameWnd (для SDI-приложений) или CMDIFrameWnd (для MDI-приложений). То, что делалось до сих пор, заключалось в создании некоторых необходимых оконных объектов и самостоятельной организации взаимодействия между ними. Мы полностью (более того — сознательно) игнорировали такое мощное средство, заложенное разработчиками в библиотеку классов MFC, как архитектура "документ/представление" (document/view).
В основе этой архитектуры лежат три глобальных понятия — фрейм, документ и представление. И если с фреймом мы уже достаточно близко ознакомились (некоторые его свойства, связанные с архитектурой "документ/представление", будут рассмотрены чуть ниже), то два других необходимо рассмотреть подробно, что мы и сделаем в следующей главе. Здесь же просто определим их место в архитектуре "документ/представление".
Что же включают в себя эти понятия? В самом общем случае, под документом фирма Microsoft понимает те данные, с которыми работает приложение. Это может быть все, что угодно, — "простой" текст, картинка и т. п. Отображение этих данных на экране осуществляется в так называемом фрейме документа. Разработчики библиотеки MFC создали для фреймов специальные классы окон — представления, которые отображают данные документа и управляют взаимодействием пользователя с ними. Другими словами, способ хранения данных в памяти или на диске никоим образом не влияет на их внешнее представление пользователю.1
Роль фрейма в этой архитектуре заключается в создании соответствующих фреймов документов, содержащих специальные окна - представления. Кроме того, фрейм осуществляет координацию взаимодействия между документами различных типов и их представлениями, направляя им команды и получая от них извещения. Маршруты, по которым осуществляется передача сообщений, подробно описаны нами в четвертой части.
Архитектура "документ/представление" разделяет между собой данные^ документы, и их изображения. Каждый документ представлен в виде объекта, который обеспечивает пространство для хранения данных в памяти и отвечает за такие операции, как запись и чтение документа с диска. Очевидно, что большая часть таких операций выполняется самим приложением, а не классами библиотеки MFC. Кроме того, для каждого используемого представления также создается отдельный объект, который представляет собой экранное окно, отвечающее за взаимодействие с пользователем и соответствующим объектом документа, печать и т. д. Совместную работу перечисленных объектов координирует фрейм, который, в большинстве случаев, является главным окном приложения (рис. 31).
Когда запускается приложение под Windows, пользователь взаимодействует с документами посредством их изображений во фреймах. Фреймы документов имеют два основных компонента: собственно фрейм и его содержимое. Для них библиотека MFC использует два различных класса. Класс фрейма управляет непосредственно фреймом, а класс представления — его содержимым. При этом окно представления является дочерним по отношению к фрейму, т. е. размещается в его рабочей области. Сам фрейм документа может быть окном SDI-приложения или дочерним окном MDI-приложения.Рис. 31. Взаимосвязь между фреймом, документом и представлением
Работа с основными компонентами фрейма документа осуществляется также по-разному. За взаимодействие пользователя непосредственно с фреймом (изменение размеров, перемещение и т. д.) полностью отвечает
сама система Windows. Управление же содержимым фрейма, т. е. представлениями, ложится на плечи разработчика.
Для координации создания и взаимодействия трех основных объектов рассматриваемой архитектуры в библиотеке классов MFC используются специальные классы шаблонов документов, которые создаются и управляются объектом "приложение".
Таким образом, архитектура "документ/представление" охватывает следующие основные классы:1 Q CWinApp — класс для создания единственного объекта — приложения;
Q CFrameWnd — класс для создания главного окна однодокументного приложения и базовый для классов CMDIFrameWnd и CMDIChildWnd, которые отвечают за работу многодокументного приложения;
О CDocTemplate — базовый абстрактный класс для создания шаблонов документов; при работе с однодокументным приложением используется производный от него класс С Single DocTemplate, а для многодокументных — класс CMultiDocTemplate\
Q CDocument — класс для создания собственно документа;
Q CView — базовый класс, который совместно со своими производными классами — CCtHView, CEditView, CListView, CTreeView и С'Scroll'View — отвечает за отображение данных документа и за взаимодействие с пользователем; для этих же целей можно использовать класс CSplitterWnd.
Нам осталось рассмотреть вопросы их создания и взаимодействия.
Место объекта-приложения в архитектуре "документ/представление"
Класс CWinApp был нами достаточно подробно рассмотрен в первом томе, и нет смысла повторяться. Однако при этом мы не касались его свойств, связанных с архитектурой "документ/представление", отложив обсуждение этого вопроса до более удобного момента. Теперь пришло время заполнить этот пробел.
Но прежде чем обсуждать роль класса CWinApp ъ рассматриваемой архитектуре, необходимо ввести понятие шаблона документа.
Приложение может поддерживать произвольное число типов документов. И единственное, что для этого нужно
— создать и "зарегистрировать" во время инициализации объекта-приложения (при выполнении функции Initlnstance) необходимое число шаблонов документов. Причем для каждого типа документа, с которым предполагается работа, используется свой шаблон. Ца-пример, если приложение поддерживает документы двух разных типов — табличные и текстовые, то оно должно создать для них два разных шаблона.
В библиотеке классов MFC для работы с шаблонами документов реализованы специальный класс —
CDocTemplate и два производных от него, — CSingleDocTemplate и CMultiDocTemplate. Рассмотрим возможности,
которые в них заложены.
Класс CDocTemplate
Это абстрактный класс, в котором реализованы ос-новные функциональные возможности для работы с шаблонами документов — организация и управление взаимодействием между классами трех типов:
Q классом документа, образованного из CDocument, Q классом представления, который изображает дан-
ные докУмента- Можно создать этот класс на базе < CView, CScrollView, CFormView, CEditView и т. д.
(CEditView можно использовать непосредственно
для текстовых документов),
U классом фрейма, который содержит представление. Для SDI-приложений он создается на основе CFrameWnd, а для MDl-приложений — на базе CMDIChildWnd. Базовые классы можно использовать и непосредственно.
Рассмотрим основные компоненты этого класса. Начнем, как обычно, с конструктора, который фиксирует типы документа, фрейма и представления, доступные для работы с данным шаблоном.
CDocTemplate::CDocTemplate( UINT nIDResource, CRuntimeClass *pDocClass, CRuntimeClass *pFrameClass, CRuntimeClass *pViewClass) —
создает объект класса. В качестве аргументов используются: nIDResource — идентификатор ресурсов (меню, акселераторы и строка описания типа шаблона документа), используемых с этим типом документов; pDocClass —
указатель на объект CRuntimeClass, отвечающий за данные документа; pFrameClass — указатель на объект CRuntimeClass, характеризующий фрейм документа; pView-Class — указатель на объект CRuntimeClass, отвечающий за представление документа. Эти объекты должны быть уже определены к моменту создания объекта "шаблон документа". Память под этот объект следует распределять динамически, и полученный указатель передать в качествепараметравфункциюCWinApp::AddDocTemplate.
virtual void CDocTemplate::AddDocument(CDocument *pDoc),
virtual void CDocTemplate::RemoveDocument(CDocument *pDoc) —
добавляет ( или удаляет) документ, на который указывает pDoc, в список документов, ассоциированных с этим шаблоном. В производных классах CSingle-DocTemplate и CMultiDocTemplate эти функции переопределены.
virtual void CDocTemplate::LoadTemplate() —
загружает ресурсы для данного шаблона документа. Обычно вызывается библиотекой классов во время создания объекта и практически не требует прямого вызова. Исключение составляет случай, когда объект класса создается на глобальном уровне. В этом случае во время выполнения функции CWinApp::AddDocTemplate необходим ее явный вызов. В качестве ресурсов, используемых документами этого типа, могут использоваться меню, акселераторы и единственный строковыйресурс.
Рассмотрим структуру строки описания типа более подробно
/ Строка описания типа шаблона документа STRINGTABLE PRELOAD DISCARDABLE BEGIN IDR_NOTETYPE "\nNote\nNote\nNote Files (*.tnd)\n.tnd
\nNote,Document\nNote Document" END
Как видите, он состоит из семи подстрок (первая — пустая), разделенных символом "\п", которые содержат дополнительную информацию о типе документа:1
О Заголовок главного окна SDI-приложения (Main frame caption). He используется для MDI-приложений;
Q Имя файла, присваиваемое новому документу по умолчанию (Doc type name) — Note. Если эта подстрока отсутствует, то используется имя Unfitted или его аналог для локализованных версий Windows (БезИмени — для русской версии);
Q Имя типа документа (File new name (OLE short name)) — Note. Если ъ приложении определено больше одного шаблона, то при создании нового документа на экране отображается блок диалога для выбора типа создаваемого документа;
G Описание типа документа и его фильтра (Filter name) — Note Files (*.tnd). Эта строка отображается в списке типов документов стандартных блоков диалога Open (Открыть) и Save As (Сохранить как);
Q Расширение, используемое для документов этого типа (File extension) — .tnd;
Q Идентификатор типа документа, хранящийся в реестре Windows (File type ID), — Note.Document;
Q Имя типа документа, хранящееся в реестре Windows (File new name (OLE long name)), — Note Document. Это же имя используется в качестве длинного имени объекта OLE, если в приложение включена соответствующая
поддержка.
Если какая-либо из этих подстрок не включается в строку, то вместо нее обязательно используется разделяющий символ "\п". Заключительный символ "\п" в строке является необязательным.
virtual BOOL CDocTemplate::GetDocString( CStringS rString,
enum DocStringlndex index) —
позволяет получить определенную подстроку описывающую тип документа, которая хранится в шаблоне и получена из соответствующей строки файла ресурсов приложения. Найденная подстрока записывается в rString. Параметр index определяет индекс подстроки, информацию о котором необходимо получить. Он может принимать одно из следующих значений:
CDocTemplate::windowTitle |
имя, отображаемое в заголовке главного |
окна приложения; представлено только в шаблонедокументадляSDI-приложений. |
|
CDocTemplate::docName |
основа имени документа; имя нового до- |
кумента этого типа складывается из основы, к которой добавляется число; если значение не определено, то по умолчанию используется Unfitted (для русской версии Windows - БезИмени).
CDocTemplate::fileNewName |
|
|
имя типа этого документа; если значение |
|
|
|||||
не |
определено, |
то |
этот |
тип |
документа |
недоступен |
при |
выполнении |
команды |
File\New |
(Файл\Создать).CDocTemplate::filterNewName |
|
|
|
|
|
CDocTemplate::filterExt
CDocTemplate::regFileTypeld
CDocTemplate::regFileTypeName
описание типа документа и нейтрального символа для фильтра, сопоставляемого с документами этого типа; эта строка изображается в списке типов файлов в блоке диалога File Open (Открыть файл); если значение не определено, то этот тип документа недоступен привыполнении команды File\0pen (ФайлЮткрыть).
расширение документов этого типа; если значение не определено, то этот тип документа недоступен при выполнении команды File\Open (ФайлЮткрыть).
идентификатор типа документа, хранящийся в реестре Windows; эта строка только для внутреннего использования; если неопределена, то тип документа не может быть зарегистрирован в File Manager (Диспетчерфайлов).
имя типа документа, хранящегося в регистрационной базе данных; эта строка может быть отображена в блоках диалога приложения, вызываемыхдлядоступакрегистрационнойбазеданных.
virtual BOOL CDocTemplate::SaveAIIModified() -
позволяетсохранитьвсемодифицированныедокументы, которыеассоциированысэтимшаблоном.
virtual void CDocTemplate::CloseAIIDocuments(BOOL bEndSession) —
позволяет закрыть все открытые документы. Обычно используется как часть кода, обрабатывающего команду Exit (Выход). Реализация по умолчанию вызывает функцию CDocument::DeleteContents, которая удаляет данные из документов и закрывает фреймы всех представлений, присоединенных к документу. Параметр bEndSession определяет, нужно ли завершать сеанс работы (TRUE) или нет (FALSE). Если перед закрытием документа необходимо выполнить какиелибо специфическиедействия, тофункциюследуетпереопределить.
Кроме вышеперечисленных, в классе объявлены еще четыре "чистые" функции: GetFirsrDocPosition, GetNextDoc, OpenFileName и SetDefaultTitle. Наличие этих функций превращает CDocTemplate в абстрактный класс и, следовательно, его нельзя использовать непосредственно. Обычно приложения используют один из двух производных от него классов, предоставляемых библиотекой MFC: С Single DocTemplate — для SDI- и CMultiDocTemplate — для MDI-приложений.
Если по каким-либо причинам может потребоваться интерфейс, который фундаментально отличается от SDI и MDI, то можно образовать свой класс непосредственно из CDocTemplate.
Для полноты картины приведем прототипы еще нескольких функций этого класса, которые в явном виде используются достаточно редко, но в некоторых случаях могут быть полезны.
Если шаблон поддерживает несколько типов файлов, то, используя функцию MatchDocType для каждого шаблона, можно определить, какие шаблоны документов подходят для данного файла, и выбрать тот, который нужен:
virtual Confidence CDocTemplate::MatchDocType( LPCTSTR IpszPathName,
CDocument *&rpDocMatch) —
служит для определения типа шаблона документа, используемого для открытия файла. Параметры: IpszPathName — полное имя файла; rpDocMatch — указатель на уже открытый документ, если файл, определенный в IpszPathName, уже открыт. Функция возвращает значение, определенное в перечислении Confidence
enum Confidence { noAttempt, maybeAttemptForeign, maybeAttemptNative, yesbeAttemptForeign, yesbeAttemptNative, yesAlreadyOpen
Если файл, определенный в параметре IpszPathName, уже открыт, то функция возвращает