在CSingleDocTemplate::OpenDocumentFile()或CMultiDocTemplate::OpenDocumentFile()的过程中,前者根据需要CreateNewFrame(),后者则一直CreateNewFrame()。之后需要调用CDocTemplate::InitialUpdateFrame()。
CDocument* CSingle/MultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMakeVisible)
{
...
CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);
...
InitialUpdateFrame(pFrame, pDocument, bMakeVisible);//因此对于单文档来说,同一个视图的OnInitialUpdate()将被调用多次!(CeateNewFrame里的LoadFrame和InitialUpdateFrame会发出了WM_INITIALUPDATE消息)而多文档每次都创建新的文档、子框架窗口和视图,因此OnInitialUpdate只会被调用两次。
...
}
void CDocTemplate::InitialUpdateFrame(CFrameWnd* pFrame, CDocument* pDoc,BOOL bMakeVisible)
{
// just delagate to implementation in CFrameWnd
pFrame->InitialUpdateFrame(pDoc, bMakeVisible);
}
void CFrameWnd::InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible)
{
// if the frame does not have an active view, set to first pane
CView* pView = NULL;
if (GetActiveView() == NULL)//对于单文档,只有第一次为NULL;对于多文档,必然为NULL,即此时还没有活动视
{
CWnd* pWnd = GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
// CWnd* GetDescendantWindow( int nID, BOOL bOnlyPerm = FALSE ) const;
返回一个CWnd对象的指针,如果没有找到子窗口,则返回NULL。nID指定了要获取的控件或子窗口的标识符。bOnlyPerm指定了返回的窗口是否可以是临时的。如果为TRUE,则只能返回永久性的窗口;如果为FALSE,则该函数可以返回临时窗口。调用这个函数以找到给定的ID所指定的后代窗口。这个成员函数搜索整个子窗口树,并不仅是直接子窗口。
if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CView)))
{
pView = (CView*)pWnd;
SetActiveView(pView, FALSE);//找到一个子窗口(视图)设置为活动视
}
}
if (bMakeVisible)
{
// send initial update to all views (and other controls) in the frame
SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE); //发出WM_INITIALUPDATE消息,调用OnInitialUpdate()。
// give view a chance to sa