Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Функции взаимодействия «документ-вид»




 

Вы уже знаете, что объект «документ» содержит данные, а объект «вид» представляет их на экране и позволяет редактировать. В SDI-приложении есть класс «документ», производный от CDocument и один или несколько классов «вид», каждый из которых, в конечном счете происходит от CView. Документ, окно представления и остальные элементы каркаса приложений взаимодействуют весьма тесно. Чтобы в этом разобраться, надо познакомиться с пятью важными функциями-членами классов «документ» и «вид». Две из них — невиртуальные функции базового класса, вызываемые производными классами, остальные — виртуальные функции, часто переопределяемые в производных классах. Рассмотрим их по порядку.

Функция CView::GetDocument

 

С объектом «вид» связан один и только один объект «документ». Функция GetDocument() позволяет выяснить, какому документу сопоставлено данное окно представления. Допустим, объект «вид» получил сообщение о том, что пользователь ввел новые данные в поле ввода. Он должен уведомить об этом документ, чтобы тот обновил свои внутренние данные. GetDocument возвращает указатель на документ; через этот указатель можно обращаться к функциям-членам или открытым переменным-членам класса «документ».

ПРИМЕЧАНИЕ Функция CDocument::GetNextView() позволяет перейти от документа к представлению, но так как у документа может быть несколько представлений, ее надо вызывать в цикле для каждого из них. Впрочем, Вы будете использовать функцию GetNextView редко — каркас приложений предоставляет более эффективный способ перебора представлений документа.

 

Генерируя класс, производный от CView, мастер создает специальную версию функции GetDocument() для безопасного приведения типов; она возвращает указатель не на CDocument, a на объект производного класса. Эта подставляемая (inline) функция выглядит примерно так:

CMyDoc * GetDocument()

{

return  (CMyDoc*) m_pDocument;

}

 

Встретив в коде вашего класса «вид» вызов GetDocument(), компилятор использует версию из производного класса, а не из CDocument, поэтому Вам не надо приводить указатель к производному классу документа.

 

Функция CDocument::UpdateAllViews

 

Если содержание документа по какой-либо причине изменилось, надо уведомить об этом все объекты «вид», чтобы те обновили представление данных. При вызове UpdateAllViews() из функции-члена производного класса документа ее первый параметр pSender равен NULL. Если же она вызывается посредством функции-члена производного класса «вид», параметр pSender указывает на текущий объект «вид»:

GetDocument()->UpdateAllViews(this);

 

Значение параметра, отличное от NULL, позволяет каркасу приложений не уведомлять текущий объект «вид» — предполагается, что он уже обновился сам.

У этой функции есть необязательные параметры, через которые можно передавать объекту специфичную для приложения информацию о том, какие части представления следует обновить. Как именно уведомляется объект при вызове UpdateAllViews()? Для ответа на этот вопрос сначала рассмотрим другую функцию — OnUpdate.

 

Функция CView::OnUpdate

 

Это виртуальная функция, вызываемая каркасом приложений в ответ на вызов вашей программой функции UpdateAllViews(). Конечно, Вы можете вызывать ее прямо в своем классе, производном от CView. Обычно функция OnUpdate() из производного класса обращается к документу и, получив его обновленные данные, либо обновляет переменные-члены класса или соответствующие элементы управления, либо объявляет часть представления недействительной, что заставляет функцию OnDraw() перерисовать часть окна по данным документа. Реализация функции OnUpdate() может выглядеть примерно так:

void CMyView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint){ CMyDocument* pMyDoc = GetDocument(); CString lastName = pMyDoc->GetLastName(); m_pNameStatic->SetWindowText(lastName); // m_pNameStatic является членом                                             // класса CMyView}

 

Вспомогательная информация передается (последние два параметра) в эту функцию функцией UpdateAllViews(). Исходная реализация OnUpdate() объявляет недействительным все окно представления. В переопределенной версии Вы можете объявить недействительным прямоугольник меньшего размера — в соответствии с информацией, полученной от UpdateAllViews (через последние два параметра).

Если CDocument-функция UpdateAllViews() вызывается с параметром pSender, указывающим на конкретный объект «вид», то OnUpdtae() вызывается для всех представлений документа, кроме заданного в параметре.

 

Функция CView::OnInitialUpdate

 

Эта виртуальная функция класса CView вызывается при запуске приложения, а также при выборе команд New или Open меню File. Версия OnInitialUpdate() в базовом классе CView просто вызывает OnUpdate. Если Вы переопределили ее в своем производном классе, убедитесь, что она вызывает OnInitialUpdate() базового класса или OnUpdate() производного класса.

Функция OnInitialUpdate() производного класса пригодна для инициализации объекта «вид». При запуске программы каркас приложений вызывает OnInitialUpdate() сразу после вызова OnCreate(), если Вы задействовали OnCreate() в своем производном классе «вид». Функция OnCreate() вызывается только один раз, но OnInitialUpdate() можно вызывать сколько угодно раз.

 

Функция CDocument::OnNewDocument

 

Эту виртуальную функцию каркас приложений вызывает после создания объекта «вид» или выбора в меню File SDI-приложения команды New. Именно здесь удобнее всего инициализировать переменные-члены вашего класса «документ». Для производного класса документа мастер генерирует переопределенную функцию OnNewDocument(). Обязательно оставьте в ней вызов функции базового класса.

Простейшее приложение на базе архитектуры «документ-вид»

 

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

  1. В заголовочном файле производного класса документа, сгенерированном мастером, объявите переменные-члены, в которых хранятся основные данные программы. Объявите их открытыми или сделайте производный класс «вид» дружественным классу документа. Хорошим стилем программирования будет объявить эти данные закрытыми и предоставить функции для их чтения и записи.
  2. В производном классе «вид» переопределите виртуальную функцию OnInitialUpdate(). Каркас приложений вызывает ее после инициализации или считывания с диска данных документа. Функция OnInitialUpdate должна обновить представление, чтобы оно отражало текущее содержание документа.
  3. Сделайте так, чтобы обработчики оконных и командных сообщений и функция OnDraw() в производном классе «вида» имели прямой доступ к переменным-членам класса «документ», используя для этого функцию GetDocument().

 

В нашей упрощенной среде «документ-вид» события будут разворачиваться в такой последовательности:

Запуск программы Создается объект CMyDocument
  Создается объект CMyView
  Создается окно представления
  Вызывается CMyView::OnCreate() (если она есть в этом классе)
  Вызывается CMyDocument::OnNewDocument()
  Вызывается CViewOnInitialUpdate() и
  инициализируется объект «вид»
  окно представления объявляется недействительным
  вызывается CMyView::OnDraw()
Пользователь ре­дакти­ру­ет данные CMyView-функции обновляют переменные-члены класса CMyDocument
Завершение работы программы Уничтожается объект CMyView
  Уничтожается объект CMyDocument

 

 

Класс CObject

 

Если посмотреть на иерархию MFC-классов, что на ее вершине находится класс CObject. Остальные классы, кроме CString и таких простых, как CRect и CPoint, — производные от корневого класса CObject. Класс, производный от CObject, наследует ряд важных характеристик. Многие преимущества этого станут очевидны при дальнейшем изучении классов MFC.

В этом разделе мы рассмотрим, как наследование от CObject позволяет задействовать объекты в организации вывода диагностической информации, а также включать их в классы наборов (collection classes).










Последнее изменение этой страницы: 2018-04-12; просмотров: 533.

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