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