使用 MFC 串行化數據和 C++ 對象(一)

串行化數據

  ——例子程序:Memo

  創建一個新的單文檔 SDI 應用,視圖類選擇 CFormView,以便用戶可以在窗口中輸入。 在界面中創建三個編輯框,然後再添加三個相應的編輯框變量。這三個變量是視圖類的成員變量,爲了交互數據,文檔類中也要創建三個對應的變量。然後,文檔類和視圖類都要對數據成員進行初始化操作,在文檔類中這個工作通常都在 OnNewDocument() 函數中進行。因爲下面任何一個操作發生時都觸發文檔類 OnNewDocument()函數執行:

  當用戶啓動應用程序;

  當用戶在“File”菜單中選擇“New”選項;

  視圖類的初始化通常由 OnInitialUpdate() 負責,下面的任何一個操作發生時,代碼都會觸發視圖類 OnInitialUpdate()函數執行 :

  當用戶啓動應用程序;

  當用戶在“File”菜單中選擇“New”選項;

  當用戶從“File”菜單中選擇 “Open”選項;

  在視圖類中獲得文檔類指針的方法是:CFooDoc* pDoc = GerDocument();

  用此文檔指針便可以操作文檔類數據:m_ViewData = pDoc->m_DocData;

  串行化的代碼很簡單,ar 是一個與用戶選擇的文件相對應的文檔對象(CArchive 對象):

// CFooDoc 序列化
void CFooDoc::Serialize(CArchive& ar)
{

if (ar.IsStoring())

{

// 將數據寫入文件

 ar << m_DocData;

}

else

{

// 從文件中讀取數據

 ar >> m_DocData;

}
}

  這樣就將數據寫入了文件,選擇“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();

發佈了3 篇原創文章 · 獲贊 29 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章