一,、UpdateAllViews 如果文檔的數(shù)據(jù)改變了,,所有的視圖都要通知到,,所以一般在派生類的文檔類調(diào)用UpdateAllViews函數(shù),, 注意: (1),、UpdateAllViews(this)表示不在通知當(dāng)前的視圖,,當(dāng)然這里已經(jīng)假定當(dāng)前視圖(GetActiveView)已經(jīng)更新 (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調(diào)用了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); //使整個視圖無效,發(fā)出WM_PAINT消息 } 促使OnPaint()被調(diào)用 void CView::OnPaint() { // standard paint routine CPaintDC dc(this); //在構(gòu)造函數(shù)中,,BeginPaint函數(shù)被調(diào)用,,聯(lián)想WIN32 API中響應(yīng)WM_PAINT消息的做法 OnPrepareDC(&dc); //如果不是打印工作,什么都不做 OnDraw(&dc); //在dc(堆棧變量,,要自動釋放)的析構(gòu)函數(shù)中,,調(diào)用了EndPaint函數(shù) } 然后調(diào)用OnDraw(&dc)虛函數(shù),這里就是通常我們在C**View中看到的C**View::OnDraw(CDC* pDC),。在這里面做一些顯示工作,。 二、OnInitialUpdate 到用戶選擇了FILE 中的NEW,,則會引起CView::OnInitialUpdate的調(diào)用 void CView::OnInitialUpdate() { OnUpdate(NULL, 0, NULL); // initial update } 默認(rèn)的CView::OnInitialUpdate除了調(diào)用OnUpdate什么都不做,,可以重寫這個虛函數(shù),對視圖對象進(jìn)行初始化,,OnInitialUpdate可以被調(diào)用多次,。 三、OnNewDocument 調(diào)用時機: (1),、在文檔對象被構(gòu)造之后(應(yīng)用程序第一次啟動時,,實質(zhì)是執(zhí)行了一個file/new 命令,只是沒有構(gòu)造) (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; } 設(shè)置是文檔數(shù)據(jù)成員初始值的好地方,,OnNewDocument要調(diào)用虛函數(shù)DeleteContents()。在CDocument中 void CDocument::DeleteContents() { } 該函數(shù)什么都不做,,需要派生文檔類去重寫它,, 特別提醒: 1、因為SDI中,,只有在關(guān)閉應(yīng)用程序的時候,,文檔對象才會調(diào)用析構(gòu)函數(shù),所以在析構(gòu)函數(shù)中完成所有文檔共有的成員變量的刪除工作,,而在DeleteContents函數(shù)中完成與某個特定文檔相關(guān)的數(shù)據(jù)的刪除工作,。 2、在MDI中,,則沒有必要注意這點,,因為文檔對象可以被多次創(chuàng)建 四、簡單的SDI程序啟動時候的流程如下: 1,、CHelloApp::CHelloApp() 全局變量的構(gòu)造函數(shù) 在int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)函數(shù)中 { ............... ............... if (!pThread->InitInstance()) //一般在應(yīng)用程序派生類重寫InitInstance虛函數(shù) { 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(); //進(jìn)入消息循環(huán) ................ } 2,、 在CHelloApp::InitInstance()虛函數(shù)中 { 創(chuàng)建了文檔模版,并加入文檔模版鏈 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程序啟動時,,默認(rèn)的ShellCommand是:file/new, 啟動的時候只是構(gòu)造空的文檔對象 (2),、在SDI中,,文檔、主框架,、視圖對象都只被創(chuàng)建一次,,所以再次使用file/new的時候,只完成 BOOL CHelloDoc::OnNewDocument() void CHelloDoc::DeleteContents() void CHelloView::OnInitialUpdate(),,這3個步驟 五,、打開文件(file/open) 1、選擇文件 2,、調(diào)用CDocument::OnOpenDocument函數(shù)(其中:刪除文檔的內(nèi)容,,并進(jìn)行了序列化) 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(); //刪除文檔的內(nèi)容 SetModifiedFlag(); // dirty during de-serialize //表明改變了文檔內(nèi)容 CArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete); loadArchive.m_pDocument = this; loadArchive.m_bForceFlat = FALSE; //把CArchive對象與文件關(guān)聯(lián)起來,用于序列化 TRY { CWaitCursor wait; if (pFile->GetLength() != 0) Serialize(loadArchive); // load me //序列化 loadArchive.Close(); ReleaseFile(pFile, FALSE); } ....... ........ SetModifiedFlag(FALSE); // start off with unmodified //設(shè)置文檔沒有被改變 return TRUE; } 3,、調(diào)用void CHelloView::OnInitialUpdate() 函數(shù) 六,、保存文件(file/save file/save as) void CDocument::OnFileSave() { DoFileSave(); //DoFileSave()調(diào)用了DoSave() } void CDocument::OnFileSaveAs() { if (!DoSave(NULL)) TRACE0("Warning: File save-as failed.\n"); } DoSave()調(diào)用了OnSaveDocument()函數(shù),在OnSaveDocument()函數(shù)中進(jìn)行了序列化操作 七,、特別注意: file/new file/open 被映射到了應(yīng)用程序類 file/save fi |
|