Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
3 семестр, WinAPI, MFC.pdf
Скачиваний:
370
Добавлен:
15.06.2014
Размер:
6.17 Mб
Скачать

Основные положения

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

Каждое приложение, написанное для 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, уже открыт, то функция возвращает