這樣就將數據寫入了文件,選擇“File”菜單中的“Save”或者“Save as”即可完成數據的串行化。 如果沒有保存數據,退出程序是會提示用戶是否保存修改過的數據。具體細節請參考源代碼。
串行化C++對象
——例子程序:PHN
創建一個新的單文檔 SDI 應用,視圖類選擇 CFormView,以便可以有窗口中用戶可以輸入。
聲明一個要串行化的 C++ 類。如 CPhone;
文檔類的處理:
在文檔類中聲明一個 MFC CObList 類對象,這個類很有用,功能也很強,用它可以很輕鬆地維護 C++ 對象列表,例如 添加、刪除列表元素等。在文檔類的頭文件中作如下聲明:
CObList m_PhoneList;
上面的聲明可以是 public 類型,這樣其它類可以直接訪問它。也可以是 private 類型,這樣就必須聲明一個公共的訪問函數,比如:GetPhoneList(),這個函數能返回 m_PhoneList 的地址。
通常可以在文檔類的 OnNewDocument()函數中進行數據初始化;
// Create a CPhone Object
CPhone* pPhone = new CPhone();
pPhone->m_Name = "";
pPhone->m_Phone = "";
// Add new object to the m_PhoneList list
m_PhoneList.AddHead(pPhone);
在此 CPhone 類的成員變量的初始化不是必須的,因爲 CPhone 的構造函數已經完成了這個工作。AddHead()函數向 m_PhoneList 列表添加剛創建的 CPhone 對象。所以,無論什麼時候創建新文檔(如啓動應用程序)都會向 m_PhoneList 列表中添加一個空的 CPhone 對象。注意類 CObList 的成員函數 AddHead() 是向列表的“頭部”添加對象(列表的開始),所以參數是想要添加的對象的地址。
刪除 m_PhoneList
列表中的內容
因爲 m_PhoneList 是在內存中維護的,所以要隨時維護,只要下面三個事件中的任何一個事件發生,都需要從內存中刪除 m_PhoneList 列表中的對象:
用戶退出應用程序;
用戶開始一個新的文檔,如從“File”菜單中選擇“New”選項;
用戶打開一個已存在的文檔,如從“File”菜單中選擇“Open”選項;
在文檔類的頭文件中聲明刪除操作的函數:
virtual void DeleteContents();
其實現如下:
// 刪除列表中的所有項目並釋放列表對象佔用的內存
while ( ! m_PhoneList.IsEmpty() )
{
delete m_PhoneList.RemoveHead();
}
視圖類處理:
聲明視圖類的數據成員:
POSITION m_position; // 在文檔類列表中的當前位置
CObList* m_pList; // 指向文檔類的列表
在 OnInitialUpdate()函數中初始化視圖類的數據成員
POSITION m_position;
CObList* m_pList;
// 獲取文檔類指針
CFooDoc* pDoc = (CFooDoc*) GetDocument();
// 獲得文檔類 m_PhoneList 的地址
m_pList = &(pDoc->m_PhoneList);
// 獲得列表頭位置
m_position = m_pList->GetHeadPosition();
// 用文檔類數據更新視圖類數據成員
CPhone* pPhone = (CPhone*)m_pList->GetAt(m_position);
m_Name = pPhone->m_Name;
m_Phone = pPhone->m_Phone;
// 用新的數據成員變量值更新屏幕顯示
UpdateData(FALSE);
// 控制輸入焦點
((CDialog*) this)->GotoDlgCtrl(GetDlgItem(IDC_NAME));
更新文檔數據
當用戶修改了視圖類的數據成員,即修改了窗體編輯框中的內容時,執行這些代碼後也會修改文檔類的數據成員。
void CFooView::OnEnChangeName()
{
// 用屏幕輸入更新控件變量
UpdateData(TRUE);
// 獲得文檔指針
CFooDoc* pDoc =(CFooDoc*)GetDocument();
// 更新文檔
CPhone* pPhone = (CPhone*)m_pList->GetAt(m_position);
pPhone->m_Name = m_Name;
// 置修改標誌爲 TRUE
pDoc->SetModifiedFlag();
}
在列表中移動記錄,修改視圖類中相應的函數。
// 聲明一個臨時的位置變量
POSITION temp_pos;
// 用當前的列表位置更新 temp_pos
temp_pos = m_position;
// 用前一個/或後一個位置更新 temp_pos
m_pList->GetPrev(temp_pos);
if ( temp_pos == NULL)
{
// no previous element
MessageBox(_T("Bottom of file encountered!"),_T("Phone for Windows"));
}else
{
// 用列表前一個記錄內容更新視圖成員數據
m_position = temp_pos;
CPhone* pPhone = (CPhone*)m_pList->GetAt(m_position);
m_Name = pPhone->m_Name;
m_Phone = pPhone->m_Phone;
UpdateData(FALSE);
}
// 控制輸入焦點
((CDialog*) this)->GotoDlgCtrl(GetDlgItem(IDC_NAME));
添加和刪除列表記錄:
//添加記錄
// 清空屏幕輸入控制
m_Name = "";
m_Phone = "";
UpdateData(FALSE);
// 創建一個新的 CPhone 對象
CPhone* pPhone = new CPhone();
pPhone->m_Name = m_Name;
pPhone->m_Phone = m_Phone;
// 添加新的對象到列表尾部,並用新的位置更新 m_position
m_position = m_pList->AddTail(pPhone);
// 獲得文檔指針
CFooDoc* pDoc = (CFooDoc*) GetDocument();
// 置修改標誌爲 TRUE
pDoc->SetModifiedFlag();
// 控制輸入焦點
((CDialog*) this)->GotoDlgCtrl(this->GetDlgItem(IDC_NAME));
//刪除記錄
// 刪除前先保存舊的指針
CObject* pOld;
pOld = m_pList->GetAt(m_position);
// 從列表中刪除元素
m_pList->RemoveAt(m_position);
// 從內存中刪除對象
delete pOld;
// 如果列表已經清空則添加一個空記錄
if ( m_pList->IsEmpty())
{
OnBnClickedAddButton();
}
// 獲取文檔指針
CPHNDoc* pDoc = (CPHNDoc*) GetDocument();
// 置修改標誌爲 TRUE
pDoc->SetModifiedFlag();
// 顯示列表的第一條記錄
OnInitialUpdate();