Класс
для нового представления документа
При создании
второго шаблона документов мы определили новую комбинацию классов, которые будут
поддерживать функционирование окон нового типа. Клиентской областью этих окон
будет управлять класс CDrawView, к созданию которого мы и приступаем.
- Поставьте фокус на элемент
Tree дерева классов в окне Class View, вызовите контекстное меню и выберите
команду Add > Add Class.
- В окне появившегося диалога
выберите категорию MFC, шаблон MFC Class и нажмите кнопку Open.
- В окне MFC Class Wizard
задайте имя класса CDrawView и выберите класс CView в списке Base Class.
- Нажмите кнопку Finish.
Примечание
Среди классов списка Base
Class теперь есть класс CObject. Как ни странно, но в Visual Studio 6 вы не
могли бы рассчитывать на помощь ClassWizard при создании класса, производного
от CObject.
В папке проекта
появились еще два файла (DrawView.h и DrawView.cpp), которые были автоматически
включены в состав проекта. Класс приложения должен их видеть, поэтому вставьте
в конец списка директив #include файла Тгее.срр еще одну:
#include
"DrawView.h"
Внесите
изменения в интерфейс класса, так чтобы он стал:
#pragma
once
class
CTreeDoc; // Упреждающее объявление
class
CDrawView :
public CView {
DECLARE_DYNCREATE(CDrawView)
protected:
CSize
m_szView; // Размеры клиетской области окна
bool
m_bNewPoints; // Флаг режима вставки новых точек
bool
m_bReady; // Флаг готовности захвата вершины
bool
m_bLock; // Флаг захвата вершины
int
m_CurID; // Индекс полигона в массиве
HCURSOR
m_hGrab; // Курсор захвата
CPen
m_penLine; // Перо для изображения контура
CDrawView();
virtual
~CDrawView();
public:
CTreeDoc*
GetDocument()
{
return
dynamic_cast<CTreeDoc*>(m_pDocument);
}
virtual
void OnDraw(CDC* pDC);
//======
Настройка контекста устройства
void
SetDC(CDC* pDC);
//======
Перерисовка контура
void
RedrawLines (CDC *pDC, CPointS point);
DECLARE_MESSAGE_MAP()
};
Так как мы
ввели в класс новый метод GetDocument и тут же дали коды его реализации, то
класс CTreeDoc должен быть известен компилятору до того, как он познакомится
с классом CDrawView. Вставьте строку с директивой включения файла заголовков
#include
"TreeDoc.h"
в список директив
файла DrawView.cpp до строки, подключающей файл DrawView.h. Класс нового
представления старого документа имеет простое назначение: изобразить в центре
своего окна дежурный полигон m_Poly, имеющийся в составе документа. Для упрощения
этой задачи мы ввели в класс переменную CSize m_szView, которая будет хранить
текущие размеры клиентской области окна. Несколько позже мы дадим коды методов
визуального редактирования. Эти методы используют параметры текущего состояния,
которые надо инициализировать в конструкторе класса. Откройте файл с кодами
реализации класса (DrawView.cpp) и измените конструктор и функцию перерисовки
OnDraw:
CDrawView::CDrawView()
{
//======
Всё режимы редактирования выключены
m_bNewPoints
=
false;
m_bReady
=
false;
m_bLock
=
false;
m_CurID
= -1;
}
void
CDrawView: :OnDraw(CDC* pDC) { CTreeDoc* pDoc = GetDocument ();
{
//======
Настройка контекста устройства
SetDC(pDC)
;
//======
Если вершина перемещается,
//======
рисуем без заливки внутренних областей,
pDoc->m_Poly
.Draw(pDC, m_bLock) ;
}
В режиме редактирования
полигон рисуется без заливки внутренних областей, а в обычном режиме просмотра
— с заливкой. Режим выбирает пользователь, а переменная m_bLock следит за тем,
какой режим выбран. Настройка контекста устройства определяет трансформацию
изображения: увеличение и сдвиг, по формуле, обсуждавшейся в уроке 2. Метод
Setoc позволяет учесть текущие размеры окна:
void
CDrawView: :SetDC(CDC*
pDC)
{
CTreeDoc*
pDoc = GetDocument ();
//======
Режим преобразования без искажений пропорций
pDC->SetMapMode
(MM_ISOTROPIC) ;
//======Размеры
логического окна хранит документ
pDC->SetWindowExt
(pDoc->m_szDoc) ;
pDC->SetWindowOrg
(pDoc->m_szDoc.cx/2, pDoc->m_szDoc.cy/2) ;
//======
Размеры физического окна хранит представление
pDC->SetViewportExt
(m_szView.cx, -m_szView. су) ;
pDC->SetViewportOrg
(m_szView.cx/2,. m_szView.cy/2) ;
}
Способом, который
вы уже не раз применяли, введите в класс CDrawView реакцию на сообщение WM_SIZE
и измените тело функции-обработчика.
void
CDrawView: :OnSize(UINT
nType,
int ex
, int су)
{
CView:
:OnSize (nType, ex, cy) ;
//
Каркас иногда вызывает эту функцию с нулевыми сх,су
if
(cx==0 | | су==0)
return;
//======
Запоминаем размеры окна
m_szView
= CSize (ex, cy) ;
}
Вспомните способ
замещения виртуальных функций (Overrides) и используйте его для введения в класс
заготовки функции OnlnitialUpdate. Введите в нее код для подготовки инструментов,
которые понадобятся в процессе визуального редактирования данных:
void
CDrawView::OnInitialUpdate()
{
//======
Загружаем курсор перемещения
m_hGrab=((CTreeApp*)AfxGetApp())->LoadCursor(IDC_MOVE);
//===
Создаем перо перерисовки контура (при перемещении)
m_penLine.CreatePen
(PS_DOT,О,COLORREF(0)); }
Настала очередь
создания второго участника квартета, определяющего поведение окна MDI-документа.
Это заявленный нами класс CDrawFrame. Для его создания повторите те же действия,
которые вы производили при создании класса CDr awView, но при выборе родительского
класса укажите на класс cMDichildWnd (без параметра splitter). Представьте приложению
нового оркестранта, вставив директиву
#include
"DrawFrame.h"
в список уже
существующих директив файла Тгее.срр. Запустите приложение. Если вы не допустили
ошибок или устранили их, то должны увидеть диалоговое окно New со списком из
двух строк: Tree и Draw. Выбрав Draw, вы должны увидеть окно документа с заголовком
Drawl и изображенной в центре окна звездой. Нажмите кнопку New на панели инструментов
и во вновь появившемся диалоговом окне выберите на сей раз шаблон Tree. В меню
Window выберите Tile, и вы увидите два окна, причем второе будет иметь заголовок
Treel. Переводя фокус из одного окна в другое, обратите внимание на смену строк
меню главного окна. Значки в верхнем левом углу окон документов тоже должны
быть разными. Панели инструментов, как мы уже отмечали, автоматически не изменяются.
Эту функциональность мы внесем позже.