文檔的讀過程
在向?qū)?chuàng)建的應(yīng)用程序中,程序的默認(rèn)菜單有"文件"、"編輯"、"視圖"和"幫助"。當(dāng)運(yùn)行程序后,打開"文件"菜單中的"打開"命令時(shí),應(yīng)用程序會(huì)自動(dòng)打開相應(yīng)的"打開"文件通用對(duì)話框。之所以有這功能,是因?yàn)橄驅(qū)?chuàng)建的應(yīng)用程序框架中,自動(dòng)將"打開"菜單命令與CWinApp的OnFileOpen成員函數(shù)相關(guān)聯(lián)。這種關(guān)聯(lián)是通過"消息映射"來實(shí)現(xiàn)的,在CTextViewerApp類的實(shí)現(xiàn)文件TextViewer.cpp前面有這樣的代碼,如圖2所示。
圖2 應(yīng)用程序類的消息映射
"消息映射"是MFC中的一個(gè)亮點(diǎn)。在Windows操作環(huán)境中,無論是系統(tǒng)產(chǎn)生的動(dòng)作或是用戶運(yùn)行應(yīng)用程序產(chǎn)生的動(dòng)作,都稱為事件(Events)產(chǎn)生的消息(Message)。例如,用戶選擇菜單時(shí)所產(chǎn)生的消息稱為"命令"消息,而鼠標(biāo)改變窗口狀態(tài)時(shí)所產(chǎn)生的消息是"窗口"消息。只要是消息,都可以通過MFC的"消息機(jī)制"來映射。映射的目的是將消息和某個(gè)函數(shù)相關(guān)聯(lián),這樣一旦該消息產(chǎn)生就會(huì)執(zhí)行相關(guān)聯(lián)的函數(shù)。
圖2代碼中,BEGIN_MESSAGE_MAP和END_MESSAGE_MAP是MFC開始和結(jié)束消息映射宏,ON_COMMAND是專門用來映射像菜單的一些命令消息宏,它有兩個(gè)參數(shù),第一個(gè)參數(shù)用來指定命令標(biāo)識(shí),MFC中每個(gè)菜單項(xiàng)都有一個(gè)標(biāo)識(shí)值,"打開"菜單的標(biāo)識(shí)ID為ID_FILE_OPEN,第二個(gè)參數(shù)是用來指定關(guān)聯(lián)的函數(shù)。(消息映射以后還會(huì)講到)
當(dāng)用戶在通用"打開"文件對(duì)話框中指定一個(gè)文件后,應(yīng)用程序?qū)⒄{(diào)用文檔對(duì)象的 CDocument::OnOpenDocument虛成員函數(shù)。該函數(shù)將打開文件,并調(diào)用DeleteContents清除文檔對(duì)象的內(nèi)容,然后創(chuàng)建一個(gè)CArchive(歸檔類)對(duì)象用于數(shù)據(jù)的讀取,接著又自動(dòng)調(diào)用Serialize函數(shù)。之后便調(diào)用視圖對(duì)象的CView::OnInitialUpdate虛成員函數(shù)。
在這個(gè)過程中,我們可能有很多地方不理解。但我們仔細(xì)想一想就會(huì)明白許多。假如視圖中已有文檔數(shù)據(jù)顯示,為了能快速顯示和修改這些數(shù)據(jù),顯然這些數(shù)據(jù)要存儲(chǔ)在專門的內(nèi)存空間中,CArchive類對(duì)象就起到了這個(gè)作用。當(dāng)打開另一個(gè)文檔時(shí),以前在內(nèi)存中存儲(chǔ)的數(shù)據(jù)要清除,這就是DeleteContents作用,而且還要使視圖能及時(shí)更新顯示,所以要調(diào)用OnInitialUpdate函數(shù)。
上述的Serialize函數(shù)是一個(gè)很特別的函數(shù),它既可以從中讀取文檔數(shù)據(jù),也可以保存文檔數(shù)據(jù),稱為"序列化"函數(shù)。它被添加用戶的文檔類中,用來根據(jù)CArchive內(nèi)部的一個(gè)標(biāo)志來決定文檔數(shù)據(jù)的流向(讀或?qū)?,如圖3所示。
圖3 Serialize函數(shù)代碼