把檔案在磁碟上儲存下來 叫做序列化
可以使用CArchive:
寫入:
CFile file("1.txt",CFile::modeCreate | CFile::modeWrite);
CArchive ar(&file,CArchive::store);
int i=4;
float b=1.3f; //C預設用float定義而不加f的為double型
CString str="SongPeng";
ar<<i<<b<<str;
讀取:
CFile file("1.txt",CFile::modeRead);
CArchive ar(&file,CArchive::load);
int i;
float b;
CString str;
CString strRestult;
ar>>i>>b>>str;
strRestult.Format("%d %f %s",i,b,str);
MessageBox(strRestult);
在BOOL CGraphicDoc::OnNewDocument()中,我們可以設定文檔,例如:
SetTitle("SongPeng")
OnNewDocument()用來在程式運行之初構造文檔,或是建立文檔:
Called
by the framework as part of the File New command. The default
implementation of this function calls the DeleteContents member
function to ensure that the document is empty and then marks the new
document as clean. Override this function to initialize the data
structure for a new document. You should call the base class version of
this function from your override.
我們已可以在String Table中修改標題,其中的IDR_MAINFRAME中的字串原為:
Graphic/n/nGraphi/n/n/nGraphic.Document/nGraphi Document
各子串之間用/n分割,可以有空子串。
各子串定義如下:
CDocTemplate::windowTitle
Name that appears in the application window’s title bar (for example,
“Microsoft Excel”). Present only in the document template for SDI
applications.
CDocTemplate::docName Root for the default document name (for
example, “Sheet”). This root, plus a number, is used for the default
name of a new document of this type whenever the user chooses the New
command from the File menu (for example, “Sheet1” or “Sheet2”). If not
specified, “Untitled” is used as the default.
CDocTemplate::fileNewName Name of this document type. If the
application supports more than one type of document, this string is
displayed in the File New dialog box (for example, “Worksheet”). If not
specified, the document type is inaccessible using the File New command.
CDocTemplate::filterName Description of the document type and
a wildcard filter matching documents of this type. This string is
displayed in the List Files Of Type drop-down list in the File Open
dialog box (for example, “Worksheets (*.xls)”). If not specified, the
document type is inaccessible using the File Open command.
CDocTemplate::filterExt Extension for documents of this type
(for example, “.xls”). If not specified, the document type is
inaccessible using the File Open command.
CDocTemplate::regFileTypeId Identifier for the document type
to be stored in the registration database maintained by Windows. This
string is for internal use only (for example, “ExcelWorksheet”). If not
specified, the document type cannot be registered with the Windows File
Manager.
CDocTemplate::regFileTypeName Name of the document type to be
stored in the registration database. This string may be displayed in
dialog boxes of applications that access the registration database (for
example, “Microsoft Excel Worksheet”).
在前兩個/n之間加入字串,就達到修改標題的效果。
在建立工程的第四部advance選項中也能進行修改
凡是從CCmdTarget派生出的類,都可以間接接受命令訊息
建立文檔運行路徑:
void CWinApp::OnFileNew()--->void CDocManager::OnFileNew()--->
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();--->
pTemplate->OpenDocumentFile(NULL);--->CDocument*
CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)--->pDocument = CreateNewDocument();
--->pFrame = CreateNewFrame(pDocument, NULL);--->
if (!pDocument->OnNewDocument())--->BOOL CGraphicDoc::OnNewDocument()
CWinApp負責管理文件管理器
開啟文檔運行路徑
void CWinApp::OnFileOpen()--->void CDocManager::OnFileOpen()--->
DoPromptFileName--->BOOL
CDocManager::DoPromptFileName(CString& fileName, UINT nIDSTitle,
DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate*
pTemplate)--->開啟一個檔案
--->AfxGetApp()->OpenDocumentFile(newName);--->
CDocument* CWinApp::OpenDocumentFile(LPCTSTR lpszFileName)--->
CDocument* CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)--->
match = pTemplate->MatchDocType(szPath, pOpenDocument);--->
判斷pOpenDocument是否為空白,pOpenDocument用來指定是否與先前的文檔關聯,即擷取先前相同文檔的指標,如果是,不再對文檔進行操作---->
CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)--->if (pDocument == NULL)--->if (pFrame == NULL)--->
if (lpszPathName == NULL)--->if (!pDocument->OnOpenDocument(lpszPathName))--->
BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName)---->
Serialize(loadArchive);---->void CGraphicDoc::Serialize(CArchive& ar)
產生可序列化的類:
A serializable class usually has a Serialize member
function, and it usually uses the DECLARE_SERIAL and IMPLEMENT_SERIAL
macros, as described under class CObject.
分為五步:
1 . Deriving your class from CObject (or from some class derived from CObject).
2 . Overriding the Serialize member function.
3 . Using the DECLARE_SERIAL macro in the class declaration.
4 . Defining a constructor that takes no arguments.
5 . Using the IMPLEMENT_SERIAL macro in the implementation file for your class.
IMPLEMENT_SERIAL(CGraph,CObject,1),1為版本號碼,儲存和讀取時版本號碼必須相同
一個文檔類對象能和多個視類對象相關,一個視類對象只和一個文檔類對象相關.
單文檔類只有一個視類對象,要擷取視類對象的指標
要在文檔類中訪問定義在視類中的對象,首先要獲得視類的指標.需要用到函數
CDocument::GetFirstViewPosition 得到視類對象的位置
virtual POSITION GetFirstViewPosition( ) const;
A POSITION value that can be used for iteration with the GetNextView member function.
Call this function to get the position of the first view in the list of views associated with the document.
然後再調用GetNextView得到視類對象的指標
POSITION pos=GetFirstViewPosition();
CGraphicView *pView=(CGraphicView *)GetNextView(pos);
POSITION A value used to denote the position of an element in a collection; used by MFC collection classes.
我們文檔類中調用Serialize儲存一個可序列化的類的資料時實際上是利用了這個對象本身的Serialize函數,這個對象需要什麼對象,都需要在你編寫可序列化的類時去確定
void CGraph::Serialize(CArchive &ar)
{
if(ar.IsStoring())
{
ar<<m_nDrawType<<m_pOrigin<<m_pEnd;
}
else
{
ar>>m_nDrawType>>m_pOrigin>>m_pEnd;
}
}
void CGraphicDoc::Serialize(CArchive& ar)
{
POSITION pos=GetFirstViewPosition();
CGraphicView *pView=(CGraphicView *)GetNextView(pos);
if (ar.IsStoring())
{
int nCount=pView->m_obArray.GetSize();
ar<<nCount;
for(int i=0;i<nCount;i++)
{
ar<<pView->m_obArray.GetAt(i);
}
}
else
{
int nCount;
ar>>nCount;
CGraph *pGraph;
for(int i=0;i<nCount;i++)
{
ar>>pGraph;
pView->m_obArray.Add(pGraph);
}
}
}
數組的儲存:
CGraph *pGraph=new CGraph(m_nDrawType,m_pOrigin,point);
m_obArray.Add(pGraph);
CObArray incorporates the IMPLEMENT_SERIAL macro to support
serialization and dumping of its elements. If an array of CObject
pointers is stored to an archive, either with the overloaded insertion
operator or with the Serialize member function, each CObject element
is, in turn, serialized along with its array index
void CGraphicDoc::Serialize(CArchive& ar)可被修改為:
void CGraphicDoc::Serialize(CArchive& ar)
{
POSITION pos=GetFirstViewPosition();
CGraphicView *pView=(CGraphicView *)GetNextView(pos);
if (ar.IsStoring())
{
}
else
{
}
pView->m_obArrary.Serialize(ar);
}
以下是CObArray在MFC中的原始碼:
void CObArray::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
CObject::Serialize(ar);
if (ar.IsStoring())
{
ar.WriteCount(m_nSize);
for (int i = 0; i < m_nSize; i++)
ar << m_pData[i];
}
else
{
DWORD nOldSize = ar.ReadCount();
SetSize(nOldSize);
for (int i = 0; i < m_nSize; i++)
ar >> m_pData[i];
}
}
文檔類時用來管理資料的我們把CObArray m_obArray放入文檔類中
以下為自動產生類,這是在View類中準備好的可以獲得文檔來指標的函數:
CGraphicDoc* CGraphicView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGraphicDoc)));
return (CGraphicDoc*)m_pDocument;
}
在View中可以這樣調用m_obArray
CGraphicDoc *pDoc=GetDocument();
pDoc->m_obArray.Add(pGraph);
Document/View結構
在MFC中,文檔類負責管理資料,提供儲存和資料載入的功能。視類負責資料的顯示,以及給使用者提供對資料的編輯和修改功能。
MFC
給我們提供Document/View結構,將一個應用程式所需要的資料處理與顯示的函數的空殼都設計好了,這些函數都是需函數,我們可以在衍生類別中重寫
這些函數。有關檔案讀寫的操作在CDocument的Serialize函數中進行,有關資料和圖形顯示的操作在CView的OnDraw函數中進行。我
們在其衍生類別中,只需要去關注serialize和OnDraw函數就可以了,其他的細節我們不需要去理會,程式就可以良好的運行。
當我麼按下"File/Open",Application Framework會啟用檔案開啟對話方塊,讓你指定檔案名稱,然後自動調用CGraphicView::OnDraw,傳遞一個顯示DC,讓你重新繪製視窗內容。
MFC給我們提供Document/View結構,是希望我們將精力放在資料結構的設計和資料顯示的操作上,而不是把時間和精力花費在對象與對象之間,模組與模組之間的通訊上。
一個文檔對象可以和多個視類對象相關聯,而一個視類對象只能和一個文檔類對象相關聯
不管是建立文檔還是開啟另外一份文檔,都會調用DeletContents,以保證建立文檔時空的
釋放對記憶體
void CGraphicDoc::DeleteContents()
{
// TODO: Add your specialized code here and/or call the base class
int nCount;
nCount=m_obArray.GetSize();
for(int i=0;i<nCount;i++)
{
delete m_obArray.GetAt(i); //解除指標與值之間的聯絡,但沒有清除堆記憶體
m_obArray.RemoveAt(i); //清除堆記憶體
}
CDocument::DeleteContents();
}
CDocument::DeleteContents()會在開啟,建立,關閉文檔時被調用
CObArray::RemoveAt
Removes one or more elements starting at a
specified index in an array. In the process, it shifts down all the
elements above the removed element(s). It decrements the upper bound of
the array but does not free memory.RemoveAt會導致數組中資料的重排
因此,需要把以上代碼修改為
void CGraphicDoc::DeleteContents()
{
// TODO: Add your specialized code here and/or call the base class
int nCount;
nCount=m_obArray.GetSize();
for(int i=0;i<nCount;i++)
{
delete m_obArray.GetAt(i);
}
m_obArray.RemoveAll();
CDocument::DeleteContents();
}
另一種方法
while(nCount--)
{
delete m_obArray.GetAt(nCount);
m_obArray.RemoveAt(nCount);
}