一、UpdateAllViews
如果文档的数据改变了,所有的视图都要通知到,所以一般在派生类的文档类调用UpdateAllViews函数,
注意:
(1)、UpdateAllViews(this)表示不在通知当前的视图,当然这里已经假定当前视图(GetActiveView)已经更新
(2)、UpdateAllViews(NULL)通知所有的视图
void CDocument::UpdateAllViews(CView* pSender, LPARAM lHint, CObject* pHint)
// walk through all views
{
ASSERT(pSender == NULL || !m_viewList.IsEmpty());
// must have views if sent by one of them
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
ASSERT_VALID(pView);
if (pView != pSender)
pView->OnUpdate(pSender, lHint, pHint);
}
}
CDocument::UpdateAllViews调用了pView->OnUpdate(pSender, lHint, pHint);
在 CView::OnUpdate中
void CView::OnUpdate(CView* pSender, LPARAM /*lHint*/, CObject* /*pHint*/)
{
ASSERT(pSender != this);
UNUSED(pSender); // unused in release builds
// invalidate the entire pane, erase background too
Invalidate(TRUE); //使整个视图无效,发出WM_PAINT消息
}
促使OnPaint()被调用
void CView::OnPaint()
{
// standard paint routine
CPaintDC dc(this); //在构造函数中,BeginPaint函数被调用,联想WIN32 API中响应WM_PAINT消息的做法
OnPrepareDC(&dc); //如果不是打印工作,什么都不做
OnDraw(&dc);
//在dc(堆栈变量,要自动释放)的析构函数中,调用了EndPaint函数
}
然后调用OnDraw(&dc)虚函数,这里就是通常我们在C**View中看到的C**View::OnDraw(CDC* pDC)。在这里面做一些显示工作。
二、OnInitialUpdate
到用户选择了FILE 中的NEW,则会引起CView::OnInitialUpdate的调用
void CView::OnInitialUpdate()
{
OnUpdate(NULL, 0, NULL); // initial update
}
默认的CView::OnInitialUpdate除了调用OnUpdate什么都不做,可以重写这个虚函数,对视图对象进行初始化,OnInitialUpdate可以被调用多次。
三、OnNewDocument
调用时机:
(1)、在文档对象被构造之后(应用程序第一次启动时,实质是执行了一个file/new 命令,只是没有构造)
(2)、选择了file/new 命令
BOOL CDocument::OnNewDocument()
{
if (IsModified())
TRACE0("Warning: OnNewDocument replaces an unsaved document.\n");
DeleteContents();
m_strPathName.Empty(); // no path name yet
SetModifiedFlag(FALSE); // make clean
return TRUE;
}
设置是文档数据成员初始值的好地方,OnNewDocument要调用虚函数DeleteContents()。在CDocument中
void CDocument::DeleteContents()
{
}
该函数什么都不做,需要派生文档类去重写它,
特别提醒:
1、因为SDI中,只有在关闭应用程序的时候,文档对象才会调用析构函数,所以在析构函数中完成所有文档共有的成员变量的删除工作,而在DeleteContents函数中完成与某个特定文档相关的数据的删除工作。
2、在MDI中,则没有必要注意这点,因为文档对象可以被多次创建
四、简单的SDI程序启动时候的流程如下:
1、CHelloApp::CHelloApp() 全局变量的构造函数
在int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)函数中
{
...............
...............
if (!pThread->InitInstance()) //一般在应用程序派生类重写InitInstance虚函数
{
if (pThread->m_pMainWnd != NULL)
{
TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode = pThread->ExitInstance();
goto InitFailure;
}
nReturnCode = pThread->Run(); //进入消息循环
................
}
2、
在CHelloApp::InitInstance()虚函数中
{
创建了文档模版,并加入文档模版链
before call ProcessShellCommand
CHelloDoc::CHelloDoc()
CMainFrame::CMainFrame()
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
BOOL CHelloView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
BOOL CHelloView::PreCreateWindow(CREATESTRUCT& cs)
int CHelloView::OnCreate(LPCREATESTRUCT lpCreateStruct)
BOOL CHelloDoc::OnNewDocument()
void CHelloDoc::DeleteContents()
void CHelloView::OnInitialUpdate()
after call ProcessShellCommand
}
注意:
(1)、SDI程序启动时,默认的ShellCommand是:file/new, 启动的时候只是构造空的文档对象
(2)、在SDI中,文档、主框架、视图对象都只被创建一次,所以再次使用file/new的时候,只完成
BOOL CHelloDoc::OnNewDocument()
void CHelloDoc::DeleteContents()
void CHelloView::OnInitialUpdate(),这3个步骤
五、打开文件(file/open)
1、选择文件
2、调用CDocument::OnOpenDocument函数(其中:删除文档的内容,并进行了序列化)
BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName)
{
if (IsModified())
TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");
CFileException fe;
CFile* pFile = GetFile(lpszPathName,
CFile::modeRead|CFile::shareDenyWrite, &fe); //打开文件
DeleteContents(); //删除文档的内容
SetModifiedFlag(); // dirty during de-serialize //表明改变了文档内容
CArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete);
loadArchive.m_pDocument = this;
loadArchive.m_bForceFlat = FALSE; //把CArchive对象与文件关联起来,用于序列化
TRY
{
CWaitCursor wait;
if (pFile->GetLength() != 0)
Serialize(loadArchive); // load me //序列化
loadArchive.Close();
ReleaseFile(pFile, FALSE);
}
.......
........
SetModifiedFlag(FALSE); // start off with unmodified //设置文档没有被改变
return TRUE;
}
3、调用void CHelloView::OnInitialUpdate() 函数
六、保存文件(file/save file/save as)
void CDocument::OnFileSave()
{
DoFileSave(); //DoFileSave()调用了DoSave()
}
void CDocument::OnFileSaveAs()
{
if (!DoSave(NULL))
TRACE0("Warning: File save-as failed.\n");
}
DoSave()调用了OnSaveDocument()函数,在OnSaveDocument()函数中进行了序列化操作
七、特别注意:
file/new file/open 被映射到了应用程序类
file/save fi
联系客服