CDocument文檔類

 文檔類本身並沒有直接提供強大的功能實現,它只是提供了一個框架,爲文檔對象與相關的其他對象(視圖、應用程序對象及框架窗口等)進行交互提供了框架。對文檔部分的設計工作,基本上都是在這個已有框架的基礎上,添加所需要的功能代碼。
文檔類(CDocument)在MFC類庫中的層次結構如圖4-3所示。


圖4-3  CDocument在MFC類庫中的層次結構

不管是SDI應用程序還是MDI應用程序,文檔類都是從CDocument類派生出來的。
在文檔/視圖結構中,文檔的主要任務通常是對數據庫進行管理和維護,數據將保存在文檔類的成員變量中,視圖通過對這些變量的訪問來獲取或送回數據,並能通過這種方式來更新並顯示數據。
文檔還負責將數據存儲到永久的存儲介質中,通常是磁盤或數據庫,這個存取過程稱之爲串行化。
此外,文檔還可以處理來自菜單、工具欄、加速鍵等對象的命令消息(WM_ COMMAND)。除WM_COMMAND外,文檔不能處理其他的Window消息。
1.數據的串行化
串行化是指將對象寫入永久存儲介質或者將對象從永久存儲介質中讀出的過程。
串行化的基本用法是使文檔對象能夠將自身的當前數據保存到存儲介質,也能從存儲介質中讀取所保存的數據,並使用這些數據來重建對象。當用戶將數據傳遞到文檔時,對象應該知道如何將自身保存到文檔並能從文檔中讀取、重建自身。
串行化操作是通過對文檔類Serialize()函數進行重載來完成的,當使用AppWizard創建SDI或MDI應用程序框架時,將自動生成一個Serialize()函數重載的框架。
2.CArchive類和CFile類
CArchive類沒有基類,CArchive對象類似於C++中的標準輸入/輸出流,它提供了一組用於從文件讀取數據和將數據寫入文件的成員函數。可以使用“>>”和“<<”運算符像在C++中一樣進行數據的輸入/輸出。
與C++的標準輸入/輸出流不同的是標準輸入/輸出流存取的是格式化的ASCII字符串,而CArchive存取的是二進制對象,這種格式更爲有效,且用途廣泛。
在使用“>>”和“<<”運算符時,CArchive對象將作爲運算符的第一操作數據,表4-1給出了所支持的第二操作數據的數據類型。

在創建CArchive類對象前,必須創建一個CFile對象,並將其與CArchive對象相關聯。在文檔/視圖結構的實現中,這一步將由框架在調用Serialize()函數前自動完成。
在使用AppWizard創建的文檔中,當單擊打開或保存菜單項時,程序將自動創建一個指定文件的CFile對象,再創建一個指向該對象的CArchive對象,將二者都置爲相同狀態——打開或保存,然後再調用文檔類Serialize()函數,將數據寫入CArchive對象或從CArchive對象讀取數據。當Serialize()函數完成工作後,框架將先後自動銷燬CArchive對象和CFile對象。
如果要顯示創建自己的CArchive對象,可以先創建一個CFile對象,然後構造一個CArchive對象,並將CFile對象通過CArchive類的構造函數傳遞給CArchive對象。CArchive類的構造函數原型如下:

CArchive( CFile* pFile, UINT nMode, int nBufSize = 4096, void* lpBuf = NULL );


參數pFile爲CFile對象的指針;參數nMode是一個標識,它指定了對象的打開方式;參數nBufSize指定內部文件緩衝區的整數大小,以字節計算,默認大小爲4096字節;lpBuf是指向nBufSize大小提供的緩衝區的指針。
3.文檔與視圖的交互
每一種類型的文檔都有與之對應的文檔模板進行管理,文檔模板負責創建和管理當前類型的所有文檔,文檔與文檔關聯的視圖和與視圖關聯的框架窗口都由文檔模板所創建。
程序框架提供了兩個文檔模板類:CSingleDocTemplate和CMultiDocTemplate,分別用於支持SDI應用程序和MDI應用程序。
SDI應用程序一次只能使用一種類型的文件,如Windows中的畫圖、記事本等。
MDI應用程序則可以同時使用多種類型的文件,如Word、Excel等。
【實例4-1】  文檔的存取
光盤路徑   /04/CDocument
實例目的   使用串行化保存讀取文件
這個實例用來說明如何使用串行化保存讀取文件。文件名爲CDocument。
(1)創建工程
在IDE中依次選擇“File”→“New”菜單命令,或直接按快捷鍵“Ctrl+N”,打開“New”對話框。
在“New”對話框中單擊“Projects”選項卡,在列表框中選擇“MFC AppWizard(.exe)”項,在“Project name”文本框中輸入“CDocument”,其他使用默認值,單擊“OK”按鈕,彈出“MFC AppWizard-Step1”對話框。
在“MFC AppWizard-Step1”對話框中,選中“Single Document”單選框,其他使用默認值,然後單擊“Finish”按鈕,在彈出的“New Project Information”對話框中單擊“OK”按鈕,就可以完成工程的創建。
在工作區中選擇的Resource View標籤,轉到資源編輯窗口,單擊“String Table”→“String Table”條目,打開串表編輯器。找到ID爲IDR_MAINFRAME的現有字符串,雙擊打開串表的屬性對話框,並對它進行修改,該字符決定了應用程序所創建的文檔類型。將字符串內容改爲“CDocument\n\nCDoc\nMyDoc(*.mdc)\n.mdc\nCDocument.Document\n \nCDocDocument\n”,如圖4-4所示。


圖4-4  修改文檔類型字符串

(2)添加響應函數
在IDE主菜單項中依次選擇“View”→“ClassWizard”,打開MFC ClassWizard對話框,選擇“Member Maps”選項卡,在“Project”下拉列表框中選擇CDocument,在“Class name”下拉列表框中選擇“CCDocument View”。
在“Object IDs”下拉列表框中選擇CCDocument View,在Message項中選中消息WM_CHAR。
單擊“Add Function…”按鈕,添加函數消息,單擊“OK”按鈕就可以創建一個名稱爲OnChar的消息處理函數,單擊“Edit Code”按鈕退出“ClassWizard”對話框,並自動打開CDocument View.cpp文件,且定位在OnChar()函數上。
用同樣的步驟添加另一個消息,消息名爲OnInitialUpdate。添加完成後的MFC ClassWizard對話框如圖4-5所示。


圖4-5 “MFC ClassWizard”對話框

(3)添加變量
通過工作區中的ClassView標籤,CCDocument View類中添加一個CString類數據成員m_str,其步驟如下:右鍵單擊“CCDocument classes”→“CCDocument View”條目,選中“Add Member Variable”菜單命令,如圖4-6所示。


圖4-6  添加變量

彈出“Add Member Variable”對話框,在Variable Type項中輸入CString,在Variable Name項中輸入m_str,單擊“OK”按鈕。如圖4-7所示。

 
圖4-7  “Add Member Variable”對話框

用同樣的方法爲CCDocument Doc類添加一個CString類型數據成員m_strText,該成員函數用於存儲文檔中的數據。
(4)添加代碼
在CCDocumentDoc::Serialize()函數中輸入如下代碼:

void CCDocumentDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
ar<<M_STRTEXT;
}
else
{
// TODO: add loading code here
ar>>m_strText;
}
}


在CCDocumentView::OnInitialUpdate()函數中輸入以下代碼:

void CCDocumentView::OnInitialUpdate() 
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
CCDocumentDoc* pDoc = GetDocument();//獲取文檔指針
m_str=pDoc->m_strText; //獲取文檔數據
UpdateData(FALSE); //初始化窗口數據
}


這段程序從文檔對象獲取數據,並用獲取的數據對視圖進行初始化。
在CCDocumentView::OnDraw()函數中輸入如下代碼:

void CCDocumentView::OnDraw(CDC* pDC)
{
CCDocumentDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here

pDC->TextOut(100,100,m_str); //顯示數組 }


在CCDocumentView::OnChar()函數中輸入如下代碼:

void CCDocumentView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
// TODO: Add your message handler code here and/or call default
CCDocumentDoc* pDoc=GetDocument();   //獲取當前文檔對象的指針
ASSERT_VALID(pDoc);       //有效性檢查
if (nChar=='\b')        //判斷是否輸入退格鍵
m_str.Delete(m_str.GetLength()-1,1);  //去掉字符串最後一個字符
else
m_str+=nChar;       //將鍵盤輸入字符加入字符串中
Invalidate(); 
pDoc->m_strText=m_str;      //將字符串傳遞給文檔變量
pDoc->SetModifiedFlag(TRUE);     //設置最近修改的標誌
CView::OnChar(nChar, nRepCnt, nFlags);
}


這段程序實現了將鍵盤字符串輸入存儲到視圖數據m_str,並通過視圖數據將字符串傳遞到文檔數據m_strText中。
語句“pDoc”→“SetModifiedFlag(TRUE);”在文檔數據修改後設置最近的修改標誌,在用戶關閉當前文檔時,會提示用戶進行保存。
(5)編譯並運行程序
程序運行的結果,如圖4-8所示。在這裏我們鍵入的是“歡迎來到Visual C++ 6.0的世界!”。

 
圖4-8  程序運行結果

單擊“文件”→“保存”或者直接按“保存”圖標,都會彈出一個保存文件的對話框。這樣我們就實現了對文檔的存取。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章