文档负责了数据真正在永久介质中的存储和读取工作,视图呈现只是将文档中的数据以某种形式向用户呈现,因此一个文档可对应多个视图。
Invalidate(TRUE)将整个窗口设置为需要重绘的无效区域,它会产生WM_PAINT消息,这样OnDraw将被调用。
void CView::OnPaint()
{
// CPaintDC类维护显示设备
CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc);
}
假如文档中的数据发生了变化,必须通知所有链接到该文档的视图,这时候文档类的UpdateAllView函数需要被调用。
当文档数据发生变化时,文档对象调用CDocument::UpdateAllView()通知所有视图,作为响应,视图的OnUpdate()成员被调用。所以,重载的OnUpdate()应该能够根据需要,将文档数据的变化反映在视图中。CView::OnUpdate()只是简单地使客户区无效,导致客户区重画。例如:
void CView::OnUpdate(CView* pSender, LPARAM, CObject*)
{
ASSERT(pSender != this);
UNUSED(pSender); // unused in release builds
Invalidate(TRUE);
}
虚函数 OnInitialUpdate()
在初始创建、调用OnCreate()之后,或者在File/New、File/Open命令后被框架调用。基类CView::OnInitialUpdate()只是简单地调用OnUpdate(),可以重载它完成初始化工作。但注意,它可能被多次调用。
void CView::OnInitialUpdate()
{
OnUpdate(NULL, 0, NULL);
}
虚函数 CalcWindowRect
每当主框架窗口的客户区尺寸发生变化或控制条的位置发生变化,需要重新排列客户区时,调用该函数,根据视图客户区尺寸计算视图窗口的尺寸。
我们知道,排列主窗口客户区是由CFrameWnd::RecalcLayout()完成的。显然,视图的CalcWindowRect()函数也是由它触发调用的。主窗口的客户区尺寸减掉所有控制占用的部分,剩下的区域分给视图,这部分区域作为实参传入CalcWindowRect()。在CalcWindowRect()函数内,需要计算视图窗口的尺寸。
虚函数PostNcDestroy
在视图窗口关闭时最后调用的成员函数,它与CFrameWnd::PostNcDestroy完成相同的功能,即删除视图对象。代码如下:
void CView::PostNcDestroy()
{
delete this;
}
这样,可以不必关心视图的释放工作,即使它在堆中构造。
虚函数 OnActivateView
当视图被激活为活动视图,或由活动转为非活动时,调用该函数通知视图。基类的实现只是设置该视图为焦点。代码如下:
void CView::OnActivateView(BOOL bActivate, CView* pActivateView, CView*)
{
UNUSED(pActivateView); // unused in release builds
if (bActivate) // 当前状态为活动吗
{
ASSERT(pActivateView == this);
// 如果其父窗口也是活动的,则设置焦点。(在MDI中,其父框架可能是非活动的)
if (IsTopParentActive())
SetFocus();
}
}
MFC提供了丰富的CView派生类,各种不同的派生类实现了对不同种类控件的支持,以为用户提供多元化的显示界面。
CScrollView: 提供滚动支持;
CCtrlView: 支持tree、list和rich edit控件;
CDaoRecordView: 在dialog-box控件中显示数据库记录;
CEditView: 提供了一个简单的多行文本编辑器视图;
CFormView: 包含dialog-box控件,可滚动,基于对话框模板资源;
CListView: 支持列表控件视图;
CRecordView: 在dialog-box控件中显示数据库记录;
CRichEditView: 支持富文本编辑的控件视图;
CTreeView: 支持重点在树控件的文档/视图结构的视图。