MFC 串行化数据和 C++ 对象.doc_第1页
MFC 串行化数据和 C++ 对象.doc_第2页
MFC 串行化数据和 C++ 对象.doc_第3页
MFC 串行化数据和 C++ 对象.doc_第4页
MFC 串行化数据和 C++ 对象.doc_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

使用 MFC 串行化数据和 C+ 对象作者:JerryZ串行化数据 例子程序: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;这样就将数据写入了文件,选择“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 ObjectCPhone* pPhone = new CPhone();pPhone-m_Name = ;pPhone-m_Phone = ;/ Add new object to the m_PhoneList listm_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;/ 置修改标志为 TRUEpDoc-SetModifiedFlag();在列表中移动记录,修改视图类中相应的函数。 / 声明一个临时的位置变量POSITION temp_pos;/ 用当前的列表位置更新 temp_postemp_pos = m_position;/ 用前一个/或后一个位置更新 temp_pos m_pList-GetPrev(temp_pos);if ( temp_pos = NULL)/ no previous elementMessageBox(_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();/ 置修改标志为 TRUEpDoc-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();/ 置修改标志为 TRUEpDoc-SetModifiedFlag();/ 显示列表的第一条记录OnInitialUpdate();串行化处理 我们要串行化 CPhone 对象,把C+对象写入文件,所以需要在 CPhone 类的定义和实现文件中加入相应的串行化代码,首先要在 CPhone 头文件中加入一个 MFC 宏,这是串行化需要的宏,必须为它提供一个参数,也就是类的名字。/ 串行化宏定义DECLARE_SERIAL(CPhone)其次是声明串行化函数,这个原型是必须的,因为要串行化类 CPhone 对象列表,所以 CPhone 类必须有一个属于自己的 Serialize()函数:/ 串行化函数 Serialize() virtual void Serialize(CArchive& ar);在 CPhone 实现文件中也要加入对应的代码,这个宏也是串行化需要的另一个宏,它有三个参数,第一个是类名,第二个是基类名,第三个是应用程序的版本号,可以将版本号定义为任何值,当串行化数据到文件时,此版本号也要写入文件。/ 串行化宏实现IMPLEMENT_SERIAL(CPhone,CObject,0);串行化函数 Serialize() 实现 if (ar.IsStoring() ar m_Name m_Name m_Phone;这里要注意的是为了使用 CObList 类的成员函数 Serialize(),有几个前提条件需要满足: 列表类对象必须是 MFC CObject 类的派生类对象,也就是说 CPhone 类必须是 CObject 的派生类; 在列表中的对象类必须具备一个不带参数的构造函数。如果需要,也可以有其它带参数的构造函数; 必须声明和实现列表类的串行化函数 Serialize(),即 CPhone:Serialize(); 实现列表对象的串行化必须使用 DECLARE_SERIAL/IMPLEMENT_SERIAL 宏; 调用列表 Serialize()函数 这一步是串行化列表 m_PhoneList,也就是调用 m_PhoneList 的成员函数 Serialize()。在什么地方调用呢?记住,无论用户什么时候从“File”菜单中选择“Save”或者“Save as”或“Open”选项,都将执行文档类的 Serialize()函数,所以必须在文档类的 Serialize()函数中调用 m_PhoneList 的 Serialize()函数。这样一来,无论用户什么时候从 File 菜单中选择 Save/Save as 时,都将把 m_PhoneList 保存在用户选择的文件中,同样地,无论用户什么时候从选择 Open 时,都将把文件中保存的列表信息加载到 m_PhoneList 中来。m_PhoneList 的串行化调用如下:m_PhoneList.Serialize(ar);只要在文档类的 Serialize() 函数中调用上面这条语句时,必须把 ar 作为参数传入,它将完成需要串行化 m_PhoneList 列表数据的所有工作。不必在if语句中再做其它处理。定制串行化例子程序:ARCH串行化处理有时并不需要用户选择文件,此时仍要从或向一个特定文件串行化数据,本部分将描述怎样创建并定制一个 CArchive 对象。创建一个新的单文档 SDI 应用, 工程名为 ARCH。视图类仍然选择 CFormView。视图中两个编辑框和两个按钮,编辑框用于输入数据,“Save to File”按钮用于将输入的数据串行化到文件,“Load from File”按钮用于从文件中抽取数据。为简单起见,文件使用的硬编码。下面是 “Save to File”的操作代码:/ 用屏幕输入内容更新 m_Var1 和 m_Var2 UpdateData(TRUE);/ 创建文件 C:ARC.ARCCFile f;f.Open(c:arc.arc,CFile:modeCreate|CFile:modeWrite);/ 创建一个 CArchive 对象,并将文件与对象关联CArchive ar(&f,CArchive:store);/ 串行化 m_Var1 和 m_Var2 到文档arm_Var1m_Var1m_Var2;/ 关闭文档ar.Close();/ 关闭文件f.Close();/ 更新屏幕显示UpdateData(FALSE);以上是三个 MFC 串行化数据的例子,Memo 程序的功能是串行化数据到文件,Phn 程序是串行化 C+ 对象列表到文件,而 ARCH 则是定制串行化。详细实现细节请下载源代码。MFC串行化转2008-05-18 18:521.CArchive在菜单打开保存时的代码CFile file(1.txt,CFile:modeCreate | CFile:modeWrite);CArchive ar(&file,CArchive:store);int i=4;char ch=a;float f=1.3f;CString str();arichfichfstr;strResult.format(%d,%c,%f,%s,i,ch,f,str);MessageBox(strResult);以上是打开。2.文档-视类结构简介 OnNewDocument在程序启动时被调用,此时可设置文档标题,也可以在String Table的IDR_MAINFRAME的第二个后改变文档的标题。需了解的7个字符串的用途,见PPT。 在WinAPP的InitInstance()中完成DOC,View,MainFrame的归一。 当点击系统的打开和新建菜单时,有一系列的步骤。我们要记住:CWinAPP负责管理文档管理器,文档管理器有一个指针链表,且来保存文档模板的指针,文档模板指针管理三个类DOC,VIEW,MAINFRAME,使其为某文件对象服务。3.利用CArchive来保存一个类的对象,此类必须支持串行化,需要5个步骤。a.让类从CObject派生;b.覆盖Serialize()函数,在其中完成保存和读取功能;c.在.h中加入 DECLARE_SERIAL(CGraph);d.在。cpp中加入IMPLEMENT_SERIAL(CGraph, CObject, 1 );e.定义一个不带参数的构造函数。保存绘画数据到文件的简单过程a.在CGraph中增加一个画图的成员函数。也可以在View中完成相应功能。b.增加四个画图菜单。c.在View中增加LButtonDown和UP的响应,在UP中画图,在DOWN中保存点d.利用CObArray集合类来保存绘画数据e.在CGraphicDOC:Serialize()中保存和读取数据f.然后在OnDraw中重绘。4.新建和打开文档时,要注意销毁原来的数据。在DOC的DeleteContents虚函数中是较好时机。代码如下int nCount;nCount=m_obArray.GetSize();/*for(int i=0;inCount;i+)delete m_obArray.GetAt(i);/释放指针指向的内存空间/m_obArray.RemoveAt(i);/移除链表中的元素。但在此处不能这样用,会导致非法操作。因为每次RemoveAt一个,后面的就整体向前移。要用下面的方法。int nCount;nCount=m_obArray.GetSize();/*for(int i=0;im_DocData;串行化的代码很简单,ar 是一个与用户选择的文件相对应的文档对象(CArchive 对象):/ CFooDoc 序列化void CFooDoc:Serialize(CArchive& ar)if (ar.IsStoring()/ 将数据写入文件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 ObjectCPhone* pPhone = new CPhone();pPhone-m_Name = ;pPhone-m_Phone = ;/ Add new object to the m_PhoneList listm_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;/ 置修改标志为 TRUEpDoc-SetModifiedFlag();在列表中移动记录,修改视图类中相应的函数。/ 声明一个临时的位置变量POSITION temp_pos;/ 用当前的列表位置更新 temp_postemp_pos = m_position;/ 用前一个/或后一个位置更新 temp_posm_pList-GetPrev(temp_pos);if ( temp_pos = NULL)/ no previous elementMessageBox(_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_positionm_position = m_pList-AddTail(pPhone);/ 获得文档指针CFooDoc* pDoc = (CFooDoc*) GetDocument();/ 置修改标志为 TRUEpDoc-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();/ 置修改标志为 TRUEpDoc-SetModifiedFlag();/ 显示列表的第一条记录OnInitialUpdate();串行化处理我们要串行化 CPhone 对象,把C+对象写入文件,所以需要在 CPhone 类的定义和实现文件中加入相应的串行化代码,首先要在 CPhone头文件中加入一个 MFC 宏,这是串行化需要的宏,必须为它提供一个参数,也就是类的名字。/ 串行化宏定义DECLARE_SERIAL(CPhone)其次是声明串行化函数,这个原型是必须的,因为要串行化类 CPhone 对象列表,所以 CPhone 类必须有一个属于自己的Serialize()函数:/ 串行化函数 Serialize()virtual void Serialize(CArchive& ar);在 CPhone实现文件中也要加入对应的代码,这个宏也是串行化需要的另一个宏,它有三个参数,第一个是类名,第二个是基类名,第三个是应用程序的版本号,可以将版本号定义为任何值,当串行化数据到文件时,此版本号也要写入文件。/ 串行化宏实现IMPLEMENT_SERIAL(CPhone,CObject,0);串行化函数 Serialize() 实现if (ar.IsStoring()ar m_Name m_Name m_Phone;这里要注意的是为了使用 CObList 类的成员函数 Serialize(),有几个前提条件需要满足:列表类对象必须是 MFC CObject 类的派生类对象,也就是说 CPhone 类必须是 CObject 的派生类;在列表中的对象类必须具备一个不带参数的构造函数。如果需要,也可以有其它带参数的构造函数;必须声明和实现列表类的串行化函数 Serialize(),即 CPhone:Serialize();实现列表对象的串行化必须使用 DECLARE_SERIAL/IMPLEMENT_SERIAL 宏;调用列表 Serialize()函数这一步是串行化列表 m_PhoneList,也就是调用 m_PhoneList 的成员函数Serialize()。在什么地方调用呢?记住,无论用户什么时候从“File”

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论