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

Частьдокумента,видимаяв

момент

 

времениРис

 

. 36.

 

Взаимоотн

 

ошения

 

документа

 

и

 

представл

 

ения

текущий

 

Таким образом, действуя совместно, документ и его представления D содержат, изображают данные приложения и управляют ими; D предоставляют интерфейс с данными документа;

Q участвуют в чтении и записи файлов;

Опредоставляют необходимые возможности для печати данных;

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

Рассмотрим эти основные компоненты архитектуры "документ/представление" подробно и начнем с документов.

Документы

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

Для реализации документа в типичном приложении необходимо проделать следующую последовательность действий (рис. 37):

Одля каждого типа документа образовать класс на базе С Document; U добавить в него переменные для хранения всех данных документа; Q реализовать функции для чтения и модификации этих данных;

Опереопределить функцию CObject::Serialize в новом классе документа для организации чтения/записи данных документа с диска/на диск.

Создание

 

 

 

 

 

обьекта

I

 

Вызовфункции

 

"документ*

 

 

Create длясоздания

 

Создание

 

окнаWindows

 

объекта

 

 

 

 

 

•фрейм"

 

 

 

 

 

Создание

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

 

 

 

WM_CREATE:

 

фрейма

 

 

вобработчике

 

документа

 

 

OnCreate

 

 

 

 

 

 

вызывается

 

 

 

 

 

OnCreateClient

 

 

 

 

 

 

для

 

 

 

 

 

 

созданиярабочей

 

 

 

 

 

 

области

 

Открытиефайлаисозданиеархива

 

 

 

^~^

 

 

 

 

Вызовфункции

 

Вызов

 

 

^ -

 

 

 

 

 

Serialize для

 

OnNewDocument

 

 

^

 

чтениядокумента

 

 

 

 

 

Вызов

изфайла

 

 

 

 

 

OnOpenDocumen

 

 

 

 

 

 

 

 

 

t

 

Закрытиефайлаиразрушениеархива

Рис. 37. Последовательность действий при создании документа

Данные документа определяются как переменные специального класса документа, производного от CDocument. Рассмотрим, как это реализовано в приложении NoteDraw, в котором используются документы двух типов. Для текстовых документов мы использовали класс библиотеки MFC CTypedPtrList, который представляет собой связанный список указателей на объекты произвольных типов:

class CNoteDoc : public CDocument

// данные текстовых документов public :

// список указателей на объекты класса CParagraph, // содержащего параметры форматирования абзаца текста CTypedPtrListXCObList, CParagraph*> m_listPar;

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

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

class CDrawDoc : public CDocument

//данные графических документов protected:

//параметры, используемые всеми нарисованными линиями int m_nWidth;

CPen m_curPen; COLORREF m_curColor;

public:

// массив указателей на объекты класса CRect, содержащего // координаты начальной и конечной точек рисуемой линии CArray<CRect*, CRect*> m_lineArray;

CPen *GetPen() (return &m curPen; }

Помимо самих данных, в классе документа зачастую определяются специальные функции для установки и извлечения элементов данных, а также для

выполнения необходимых операций над ними (в приведенном фрагменте функция GetPen).

К последнему действию, необходимому при создании какого-либо документа приложения — переопределению функции Serialize для реализации процесса сериализации — мы еще вернемся, а пока рассмотрим "цикл жизни" документа в рамках архитектуры "документ/представление":

Ово время динамического создания вызывается конструктор объекта — "документ";

Одля каждого нового документа вызывается функция OnNewDocument или On Open Document,

Q пользователь взаимодействует с документом посредством представлений, ассоциированных с ним;

G для удаления данных документа вызывается функция DeleteContents\ О для удаления объекта "документ" вызывается его деструктор.

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

Класс CDocument

т-ттт.

Этот класс предоставляет базовые функциональные ~^~'

возможности для классов

 

документов, определенных 7;кл|

пользователем. Он поддерживает все стандартные опе-чСШёитеМ -

k

Рации> такие как создание документа, его загрузка и "-*•***-•*••-•••*•*•

сохранение. Библиотека MFC работает с

 

документами используя интерфейс, определенный в CDocument.

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

Рассмотрим функции этого класса.

CDocument: :CDocument() —

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

CDocTemplate* CDocument::GetDocTempiate() —

возвращает указатель на объект-шаблон для документа этого типа. Если документ этого типа не поддерживается какимлибо шаблоном, то возвращается NULL.

const CString& CDocument::GetPathName() -

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

virtual void CDocument::SetPathName( LPCTSTR IpszPathName,

BOOL bAddToMRU = TRUE) -

устанавливает полный путь к файлу документа на диске (параметр IpszPathName). В зависимости от значения параметра bAddToMRU этот путь добавляется (TRUE) или не добавляется (FALSE) в список последних использованных файлов (MRU).

const CStringS CDocument::GetTitle() -

возвращает название документа. Чаще всего оно образуется из имени соответствующего файла или берется из подстроки "Doc type name" соответствующей строкиресурсаописаниятипа.

virtual void CDocument::SetTit!e(LPCTSTR IpszTitle) -

устанавливает название документа (параметр IpszTitle). При этом происходит обновление заголовков всех фреймов, которыеотображаютдокумент.

BOOL CDocument::lsModified() -

возвращает TRUE, если документ был изменен после последнего сохранения, в противном случае — FALSE.

void CDocument::SetModifiedFlag(BOOL bModifitd = TRUE) -

позволяет пометить документ как модифицированный (bModified = TRUE), что позволит библиотеке MFC гарантировать вывод окна запроса пользователю на сохранениедокументадоегозакрытия. Использованиевкачестве значения параметра FALSE позволяет пометить документ как немодифицированный, даже если в него были внесеныкакие-либоизменения, неотменяяихфактически.

void CDocument::AddView(CView *pView) -

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

ID_FILE_NEW, ID_FILE_OPEN, ID_WINDOW_NEW или при разбиенииразделяемогоокна.

void CDocument::RemoveView(CView *pView) —

отсоединяет представление pView от документа и удаляет его от общего списка представлений, ассоциированных с этим документом Указатель m_pDocument класса CView устанавливается в NULL. Вызывается библиотекой MFC при закрытиифреймаилиобластиразделенногоокна.

virtual POSITION CDocument::GetFirstViewPosition() -

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

virtual CView* CDocument::GetNextView(POSITION &rPosition) -

возвращает указатель на объект класса CView (или производного от него), определяемый его позицией rPosition в списке представлений документа. После этого устанавливает rPosition в значение для следующего представления в списке. Если полученное представление последнее в списке, то rPosition устанавливается в NULL. Позиция представления в списке полностью определяется порядкомегозаписивнего.

//получаем указатель на документ, с которым // ассоциировано текущее представление

CNoteDoc* pDoc = (CNoteDoc*)GetDocumentО;

//получаем позицию первого представления, хранящегося в // списке представлений

ассоциированных с документом POSITION pos = pDoc->GetFirstViewPosition();

// получаем указатель на первое представление в списке pDoc->GetNextView(pos);

//получаем указатель на второе представление в списке CTextView *pText = (CTextView *)pDoc- >GetNextView(pos);

//читаем данные представления pText->GetSelectedText(str);

void CDocument::UpdateAIIViews( CView *pSender,

LPARAM IHint = OL, CObject *pHint = NULL) -

информирует каждое представление, присоединенное к документу, за исключением модифицировавшего документ, на которое указывает pSender о том, что документ был изменен. Это приводит к вызову функции CView::OnUpdate для каждого представления (за исключением определяемого параметром pSender), передаваяиминформациюоб изменениях в документе. Эта информация может быть представлена каким-либо кодом (параметр IHint) и/или содержаться в объекте (параметр pHint).

void CNoteView::OnPageSetup()

//после того как были изменены параметры страницы, необходимо // произвести обновление изображения данных на экране CNoteDoc* pDoc = (CNoteDoc*)GetDocument();

//сообщение об обновлении передается всем представлениям, // ассоциированным с документом, но реально предназначается // только объекту класса, на который указывает this pDoc- >UpdateAllViews(NULL, 0, this);

void CNoteView::OnUpdate(CView*,

LPARAM, CObject *pHint) {

// если определено представление,

требующее перерисовки if(pHint != NULL)

// и оно является объектом класса CNoteView ... if(pHint- >IsKindOf(RUNTIME_CLASS(CNoteView))) {

I I . . . изменяем размеры этого представления

virtual BOOL CDocument::CanCloseFrame(CFrameWnd *pFrame) —

вызывается библиотекой MFC до закрытия фрейма документа; Функция проверяет все фреймы, которые отображают документ, и если в нем^ыли какие-либо изменения, выводит на экран окно запроса на сохранение. Параметр pFrame указывает на фрейм представления, присоединенногокдокументу.

virtual void CDocument::DeleteContents() —

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

virtual void CDocument::OnChangedViewList() —

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

virtual void CDocument::OnCloseDocument() —

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

virtual BOOL CDocument::OnNewDocument() —

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

BOOL CNoteDoc::OnNewDocument() {

//всю стандартную обработку по созданию документа // возлагаем на библиотеку MFC — она делает это прекрасно! if (!CDocument::OnNewDocument()) return FALSE;

//после успешного создания проводим "настройку" // конкретного документа InitDoc();

return TRUE;

virtual BOOL CDocument::OnOpenDocument(LPCTSTR IpszPathName) —

вызывается библиотекой MFC при обработке команды ID_FILE_OPEN. Реализацияпоумолчаниюоткрываетфайл, имя которого определяется параметром IpszPathName, вызывает функцию DeleteContents, обеспечивающую очистку документа, функцию Serialize для чтения содержимого файла и помечает документ как немодифицированный. Переопределятьееследует, еслииспользуетсякакой-либоспециальныймеханизмработысархивами и/илифайлами, например, распознаваниеформатадокумента.

virtual BOOL CDocument::OnSaveDocument(LPCTSTR IpszPathName) -

вызывается библиотекой MFC при обработке команд ID_FILE_SAVE или ID_FILE_SAVE_AS. Реализация по умолчанию открывает файл, имя которого определяется параметром IpszPathName, вызывает функцию Serialize для записивфайлданныхдокументаипомечаетегокакнемодифицированный.

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

virtual void CDocument::ReportSaveLoadException( LPCTSTR IpszPathName,

CException *e, BOOL bSaving, UINT nIDPDefault) -

вызывается библиотекой MFC, если во время выполнения операций сохранения или загрузки документа произошло исключение (CFileException или CArchiveEx-ception). Реализация по умолчанию проверяет объект исключения и ожидает от объекта исключения сообщения об ошибке. Если сообщение не найдено или параметр е, определяющий объект "исключение", равен NULL, то используется сообщение, задаваемое параметром nIDPDefault. Характер выполняемой операции задается параметром bSaving: сохранение — TRUE, загрузка —

FALSE.

virtual CFile* CDocument::GetFile( LPCTSTR IpszFileName,

UINT nOpenFlags, CFileException pError) —

позволяет получить указатель на объект CFile по абсолютному или относительному пути IpszPathName к требуемому файлу. Параметр nOpenFlags задает режим доступа и совместного использования, a pError указывает на объект "исключение" приработесфайлом, вкоторыйзаписываетсяДостояниезавершенияоперации.

virtual void CDocument::ReleaseFile(

 

CFile *pFile,

,:

BOOL bAbort) -

 

освобождает файл pFile, делая его доступным для других приложений. Параметр bAbort определяет функцию, при помощи которой будет освобождаться файл: FALSE— если используется функция CFile::Close, TRUE— при вызове функции CFile::Abort.

virtual BOOL CDocument::SaveModified() -

вызывается библиотекой MFC до того, как модифицированный документ будет закрыт. Реализация по умолчанию выводит на экран окно с запросом к пользователю на подтверждение сохранения изменений в документе. Этот запрос не выводится, еслиизменениявдокументебылиблокированывызовомфункцииSetModifiedFlag(FALSE).

virtual void CDocument::PreCloseFrame(CFrameWnd *pFrame) —

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

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

OnOpenDocument. Этот случай представляет больший интерес, т. к. вплотную подводит нас к достаточно важному понятию не только в рамках архитектуры "документ/представление", но и во всей библиотеке классов MFC.