MFC 預設 CDocument::Serialize 綁定檔案儲存,但某些資料(設定檔、黑名單、快取)不需顯示於 View、不想讓用戶干預,硬塞進 Document 反而混亂架構。本文示範獨立衍生 CObject 類別實作序列化,完全脫離 Document/View。
// SerData.h
class CSerData : public CObject
{
DECLARE_SERIAL(CSerData) // 必須!啟用動態建立與序列化
public:
CSerData();
virtual ~CSerData();
virtual void Serialize(CArchive& ar); // 覆寫序列化
// 資料成員
int m_nID;
CString m_strName;
BOOL m_bIsSave;
// 操作介面
BOOL SaveData();
BOOL LoadData();
};
// SerData.cpp
IMPLEMENT_SERIAL(CSerData, CObject, 1) // 版本號 1
void CSerData::Serialize(CArchive& ar)
{
if (ar.IsLoading()) {
ar >> m_strName;
ar >> m_nID;
} else {
ar << m_strName;
ar << m_nID;
}
}
#define DATA_FILE _T("DataTest.dat")
BOOL CSerData::SaveData()
{
UINT nFlags = CFile::modeCreate | CFile::modeWrite | CFile::typeBinary;
CFile file;
CFileException fe;
if (!file.Open(DATA_FILE, nFlags, &fe))
return FALSE;
CArchive ar(&file, CArchive::store);
Serialize(ar); // 呼叫虛函數實作
ar.Close();
file.Close();
return TRUE;
}
BOOL CSerData::LoadData()
{
CFile file;
CFileException fe;
if (!file.Open(DATA_FILE, CFile::modeRead | CFile::typeBinary, &fe))
return FALSE;
CArchive ar(&file, CArchive::load);
Serialize(ar);
ar.Close();
file.Close();
return TRUE;
}
// 對話框成員
CSerData m_Data;
void CMyDialog::OnSave()
{
UpdateData(TRUE); // 從控件取得資料
m_Data.m_nID = m_nID;
m_Data.m_strName = m_strName;
if (m_Data.SaveData())
AfxMessageBox(_T("儲存成功"));
else
AfxMessageBox(_T("儲存失敗"));
}
void CMyDialog::OnLoad()
{
if (m_Data.LoadData()) {
m_nID = m_Data.m_nID;
m_strName = m_Data.m_strName;
UpdateData(FALSE); // 更新控件顯示
AfxMessageBox(_T("讀取成功"));
} else {
AfxMessageBox(_T("讀取失敗或檔案不存在"));
}
}
| 要點 | 說明 |
|---|---|
| 衍生 CObject | 序列化機制建立在 CObject 基礎上 |
| DECLARE_SERIAL / IMPLEMENT_SERIAL | 啟用動態建立、版本控制、Schema 號 |
| CArchive 配合 CFile | Store/Load 模式對應寫入/讀取 |
| 版本號管理 | IMPLEMENT_SERIAL 最後一參數為版本,舊版資料可相容讀取 |
| 錯誤處理 | CFileException 捕捉檔案 IO 錯誤 |
CArray/CList/CMap 等 MFC 容器支援序列化,成員為 CObject 衍生類別時自動遞迴。Serialize 內用 ar.GetObjectSchema() 判斷版本,條件式讀寫。CFile 衍生類別實作加密/解密,CArchive 無感知差異。不綁定 Document/View 照樣能用 MFC 強大的序列化機制。將資料邏輯封裝在獨立 CObject 衍生類別,乾淨、可重用、符合單一職責原則。下次需要「只存不顯」的資料時,請直接新增一個 CSerData 類別。