Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2622954
  • 博文数量: 315
  • 博客积分: 3901
  • 博客等级: 少校
  • 技术积分: 3640
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-08 15:32
个人简介

知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516

文章分类

全部博文(315)

文章存档

2019年(2)

2018年(1)

2016年(7)

2015年(32)

2014年(39)

2013年(109)

2012年(81)

2011年(44)

分类: WINDOWS

2013-08-25 02:20:05


1.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("");

 ar<以上是保存,打开略

 

2.文档-视类结构简介

  OnNewDocument在程序启动时被调用,此时可设置文档标题,也可以在String TableIDR_MAINFRAME的第二个"\n"后改变文档的标题。须了解的7个字符串的用途,见PPT

  WinAPPInitInstance()中完成DOC,View,MainFrame的归一。

  当点击系统的打开和新建菜单时,有一系列的步骤,孙鑫老师给我们跟踪了代码的调用过程,此段跟踪我们略过。但我们要牢记住:CWinAPP负责管理文档管理器,文档管理器有一个指针链表,且来保存文档模板的指针,文档模板指针管理三个类DOCVIEWMAINFRAME,使其为某文件对象服务。

 

3.利用CArchive来保存一个类的对象,此类必须支持串行化,需要5个步骤。

 a.让类从CObject派生;

 b.覆盖Serialize()函数,在其中完成保存和读取功能;

 c..h中加入 DECLARE_SERIAL(CGraph)

 d.在。cpp中加入IMPLEMENT_SERIAL(CGraph, CObject, 1 )

 e.定义一个不带参数的构造函数。

 

 

 保存绘画数据到文件的简单过程

 a.CGraph中增加一个画图的成员函数,其实不增加也行。可以在View中完成相应功能。

 b.增加四个画图菜单,菜单可以从11课的代码中拷贝。

 c.View中增加LButtonDownUP的响应,在UP中画图,在DOWN中保存点

 d.利用CObArray集合类来保存绘画数据

 e.CGraphicDOC::Serialize()中保存和读取数据

 f.然后在OnDraw中重绘。

 

4.新建和打开文档时,要注意销毁原来的数据。在DOCDeleteContents虚函数中是好时机。代码如下

 int nCount;

 nCount=m_obArray.GetSize();

 /*for(int i=0;i

 {

 delete m_obArray.GetAt(i);//释放指针指向的内存空间

 //m_obArray.RemoveAt(i);//移除链表中的元素。嘿嘿,别搞错了。但在此处不能这样用,会导致非法操作。要用下面的方法沙

 }

 m_obArray.RemoveAll();*/

 while(nCount--)

 {

 delete m_obArray.GetAt(nCount);

 m_obArray.RemoveAt(nCount);

 }

 

下面是具体的过程,只有代码喔

下面两点补充12讲的文件操作内容:

  1. void CWenDangView::OnXieru()   
  2. {  
  3.     // TODO: Add your command handler code here  
  4.   
  5.     CFile file("demo110.txt",CFile::modeCreate|CFile::modeWrite);  
  6.     CArchive ar(&file,CArchive::store);  
  7.     ar.Write("hello,use CArchive to show",strlen("hello,use CArchive to show"));  
  8.     ar.Close();  
  9.   
  10.     //用下面这种方式的话,如果运行程序没有关闭的话,txt文档打不开,会报错说该文件正在使用  
  11.     //CFile *file=new CFile("demo111.txt",CFile::modeCreate|CFile::modeWrite);  
  12.     //CArchive ar(file,CArchive::store);  
  13.       
  14.   
  15. }  


 

  1. void CWenDangView::OnDuqu()   
  2. {  
  3.     // TODO: Add your command handler code here  
  4.   
  5.     /*CFile file("demo110.txt",CFile::modeRead); 
  6.     CArchive ar(&file,CArchive::load); 
  7.     char ch[100]; 
  8.     memset(ch,0,100); 
  9.     ar.Read(ch,100); 
  10.     MessageBox(ch);*/  
  11.   
  12.     //或者使用这种方式:  
  13.     CFile file("demo110.txt",CFile::modeRead);  
  14.     CArchive ar(&file,CArchive::load);  
  15.     int len=file.GetLength();  
  16.     char *ch=new char[len+1];  
  17.     ar.Read(ch,len);  
  18.     ch[len]=0;  
  19.     MessageBox(ch);  
  20.       
  21. }  


在CDocument.app文件中的OnNewDocument函数中,可以设置document文件属性,如

  1. "font-size:18px;">SetTitle("hello,CDocument");  


当然,也可以在String Tablet中去设置:

 

这些个属性,可以在MSDN中 GetDocString中查到

 

 

OnXieRu

  1. CFile file("demo111.txt",CFile::modeCreate|CFile::modeWrite);  
  2.     CArchive ar(&file,CArchive::store);  
  3.     int a=123;  
  4.     char b='H';  
  5.     float d=12.354f;  
  6.     CString cstring="hello";  
  7.     ar<
  8.     ar.Close();  


OnDuQu

  1. CFile file("demo111.txt",CFile::modeRead);  
  2.     CArchive ar(&file,CArchive::load);  
  3.     int a;  
  4.     char b;  
  5.     float d;  
  6.     CString cstring;  
  7.     CString result;  
  8.     ar>>a>>b>>d>>cstring;  
  9.     result.Format("%d,%c,%f,%s",a,b,d,cstring);  
  10.     MessageBox(result);  
  11.     ar.Close();  

实践证明,write()和Read()搭配使用,操作符>>和<<搭配使用。

程序帮我们生成的菜单中,打开和保存,在程序中找不到相应的OnFileOpen和OnFileSave类似的函数,孙鑫老师为我们跟踪了函数的归宿,这几个函数是在CXXAPP文件中被管理的,打开和保存在CDocument中的Serialize函数中类完成的

  1. void CWenDangDoc::Serialize(CArchive& ar)  
  2. {  
  3.     if (ar.IsStoring())  
  4.     {  
  5.         // TODO: add storing code here  
  6.     }  
  7.     else  
  8.     {  
  9.         // TODO: add loading code here  
  10.     }  
  11. }  


 

  1. void CWenDangDoc::Serialize(CArchive& ar)  
  2. {  
  3.     if (ar.IsStoring())  
  4.     {  
  5.         // TODO: add storing code here  
  6.   
  7.         CFile file("demo112.txt",CFile::modeCreate|CFile::modeWrite);  
  8.         CArchive ar(&file,CArchive::store);  
  9.         int a=10086;  
  10.         CString cstring="hello,VC++";  
  11.           
  12.         ar<
  13.         ar.Close();  
  14.     }  
  15.     else  
  16.     {  
  17.         // TODO: add loading code here  
  18.         CFile file("demo112.txt",CFile::modeRead);  
  19.         CArchive ar(&file,CArchive::load);  
  20.         int a;  
  21.         CString cstring;  
  22.         CString result;  
  23.   
  24.         ar>>a>>cstring;  
  25.         result.Format("%d,%s",a,cstring);  
  26.         AfxMessageBox(result);  
  27.         ar.Close();  
  28.   
  29.     }  
  30. }  


运行程序,先写入,然后读取,却读取不到,这是因为设计的问题,当程序正在当前的文件,再打开当前的文件是没有反应的,就像Word文档,OnDocumentOpen里面会判断是否XXX的。

 

用CArchive去保存一个对象,这个类要是可Serialize的,要创建这样一个类,必须满足下面五个步骤

 

下面我们自己去设计一个Serialize的类,取名为HuiTu(绘图)类。

步骤1

  1. class HuiTu  :public CObject  
  2. {  
  3. public:  
  4.     HuiTu();  
  5.     virtual ~HuiTu();  
  6.   
  7. public:  
  8.     CPoint yuandian;  
  9.     CPoint zhondian;  
  10.     UINT leixing;  
  11.   
  12. };  


步骤2

  1. public:  
  2.     HuiTu();  
  3.     virtual ~HuiTu();  
  4.     void Serialize(CArchive& ar);  
  1. void HuiTu::Serialize(CArchive& ar)  
  2. {  
  3.     if(ar.IsStoring())  
  4.     {  
  5.         ar<
  6.     }  
  7.     else  
  8.     {  
  9.         ar>>leixing>>yuandian>>zhondian;  
  10.   
  11.     }  
  12. }  


步骤3

  1. class HuiTu  :public CObject  
  2. {  
  3.     DECLARE_SERIAL(HuiTu)  
  4.   
  5. public:  
  6.     HuiTu();  
  7.     virtual ~HuiTu();  
  8.     void Serialize(CArchive& ar);  
  9.   
  10. public:  
  11.     CPoint yuandian;  
  12.     CPoint zhondian;  
  13.     UINT leixing;  
  14.   
  15. };  


步骤4新建一个类的时候,已经有了默认的构造函数,如果没有,自己手动建一个

步骤5

cpp文件中,构造函数之前,加上:

  1. IMPLEMENT_SERIAL( HuiTu, CObject, 1 )  


这样 五个条件就完成了

CXXView中,左键down 点坐标赋给m_yuandian,左键up 点坐标赋给m_zhondian

HuiTu类中 添加一个成员函数:

  1. void HuiTu::Draw(CDC *pdc)  
  2. {  
  3.     CBrush *newbrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));  
  4.     CBrush *oldbrush=pdc->SelectObject(newbrush);  
  5.   
  6.     switch(leixing)  
  7.     {  
  8.     case 1:  
  9.         pdc->SetPixel(zhondian,RGB(0,0,0));  
  10.         break;  
  11.   
  12.     case 2:  
  13.         pdc->MoveTo(yuandian);  
  14.         pdc->LineTo(zhondian);  
  15.         break;  
  16.     case 3:  
  17.         pdc->Rectangle(&CRect(yuandian,zhondian));  
  18.         break;  
  19.     case 4:  
  20.         pdc->Ellipse(&CRect(yuandian,zhondian));  
  21.         break;  
  22.     default:  
  23.         break;  
  24.   
  25.     }  
  26. }  


菜单响应函数

  1. void CWenDangView::OnDian()   
  2. {  
  3.     // TODO: Add your command handler code here  
  4.     leixing=1;  
  5. }  
  6.   
  7. void CWenDangView::OnXian()   
  8. {  
  9.     // TODO: Add your command handler code here  
  10.     leixing=2;  
  11. }  
  12.   
  13. void CWenDangView::OnJuxing()   
  14. {  
  15.     // TODO: Add your command handler code here  
  16.     leixing=3;  
  17. }  
  18.   
  19. void CWenDangView::OnTuoyuan()   
  20. {  
  21.     // TODO: Add your command handler code here  
  22.     leixing=4;  
  23. }  


  1. void CWenDangView::OnLButtonUp(UINT nFlags, CPoint point)   
  2. {  
  3.     // TODO: Add your message handler code here and/or call default  
  4.   
  5.     m_zhondian=point;  
  6.   
  7.     CClientDC ccdc(this);  
  8.     CBrush *newbrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));  
  9.   
  10.     switch(m_leixing){  
  11.     case 1:  
  12.         ccdc.SetPixel(m_yuandian,RGB(0,0,0));  
  13.         break;  
  14.           
  15.     case 2:  
  16.         ccdc.MoveTo(m_yuandian);  
  17.         ccdc.LineTo(point);  
  18.         break;  
  19.     case 3:  
  20.         ccdc.Rectangle(&CRect(m_yuandian,point));  
  21.         break;  
  22.     case 4:  
  23.         ccdc.Ellipse(&CRect(m_yuandian,point));  
  24.         break;  
  25.     default:  
  26.         break;  
  27.     }  
  28.       
  29.     HuiTu *huitu;  
  30.     huitu=new HuiTu(m_leixing,m_yuandian,point);  
  31.     m_obArray.Add(huitu);  
  32.   
  33.   
  34.     CView::OnLButtonUp(nFlags, point);  
  35. }  


使用了CObArray集合来保存数据,同样可以使用Vector或者CPtrArray来保存

  1. void CWenDangDoc::Serialize(CArchive& ar)  
  2. {  
  3.   
  4.     POSITION position=GetFirstViewPosition();  
  5.     CWenDangView *wendangview=(CWenDangView*)GetNextView(position);  
  6.   
  7.     if (ar.IsStoring())  
  8.     {  
  9.         // TODO: add storing code here  
  10.   
  11.         /*CFile file("demo112.txt",CFile::modeCreate|CFile::modeWrite); 
  12.         CArchive ar(&file,CArchive::store); 
  13.         int a=10086; 
  14.         CString cstring="hello,VC++"; 
  15.          
  16.         ar< 
  17.         ar.Close();*/  
  18.   
  19.         int ncount=wendangview->m_obArray.GetSize();  
  20.         ar<
  21.         for(int i=0;i
  22.         {  
  23.             ar<m_obArray.GetAt(i);  
  24.         }  
  25.           
  26.   
  27.   
  28.     }  
  29.     else  
  30.     {  
  31.         // TODO: add loading code here  
  32.         /*CFile file("demo112.txt",CFile::modeRead); 
  33.         CArchive ar(&file,CArchive::load); 
  34.         int a; 
  35.         CString cstring; 
  36.         CString result; 
  37.  
  38.         ar>>a>>cstring; 
  39.         result.Format("%d,%s",a,cstring); 
  40.         AfxMessageBox(result); 
  41.         ar.Close();*/  
  42.   
  43.         int ncount;  
  44.         ar>>ncount;//先存先取  
  45.   
  46.         HuiTu *huitu;  
  47.         for(int i=0;i
  48.         {  
  49.             ar>>huitu;  
  50.             wendangview->m_obArray.Add(huitu);  
  51.         }  
  52.   
  53.   
  54.   
  55.     }  
  56.     //wendangview->m_obArray.Serialize(ar);  
  57. }  


 

 

  1. void CWenDangView::OnDraw(CDC* pDC)  
  2. {  
  3.     CWenDangDoc* pDoc = GetDocument();  
  4.     ASSERT_VALID(pDoc);  
  5.   
  6.     int ncount=m_obArray.GetSize();  
  7.     for(int i=0;i
  8.     {  
  9.         ((HuiTu*)m_obArray.GetAt(i))->Draw(pDC);  
  10.     }  
  11.       
  12.     // TODO: add draw code for native data here  
  13. }  

 

因为CObArray支持Serialize

所以跟下面语句跟上面一长串是等价的:

  1. void CWenDangDoc::Serialize(CArchive& ar)  
  2. {  
  3.   
  4.     POSITION position=GetFirstViewPosition();  
  5.     CWenDangView *wendangview=(CWenDangView*)GetNextView(position);  
  6.   
  7.     if (ar.IsStoring())  
  8.     {  
  9.         // TODO: add storing code here  
  10.   
  11.     }  
  12.     else  
  13.     {  
  14.           
  15.             // TODO: add storing code here  
  16.     }  
  17.     wendangview->m_obArray.Serialize(ar);//本身支持这个操作  
  18. }  


最好把数据都放在CXXDOC中去处理,如这个例子可以这样处理:

1把m_obArray定义成CXXDoc类中的成员变量(共有)

2因为CXXView中,系统已经定义好了GetDocument()函数,所以CXXView中的OnLButtonUp中

后改成:CXXDoc *pDoc=GetDocument();  pDoc->m_obArray.add(huitu);

3在CXXDoc中的Serialize函数中

else之后,m_obArray.Serialize(ar);


 

因为new了,分配了内存,所以要在文档新建或销毁的时候调用delete释放内存

CXXDOC虚函数,文档新建或销毁的时候会调用

  1. void CWenDangDoc::DeleteContents()   
  2. {  
  3.     // TODO: Add your specialized code here and/or call the base class  
  4.       
  5.     POSITION pos=GetFirstViewPosition();  
  6.     CWenDangView *wendangview=(CWenDangView*)GetNextView(pos);  
  7.   
  8.     int ncount=wendangview->m_obArray.GetSize();  
  9.     for(int i=0;i
  10.     {  
  11.         delete wendangview->m_obArray.GetAt(i);  
  12.         //wendangview->m_obArray.RemoveAt(i);//这里每删除一次,编号都会跟着改变的,这里会发生内存泄漏  
  13.     }  
  14.     wendangview->m_obArray.RemoveAll();  
  15.   
  16.     CDocument::DeleteContents();  
  17. }  


如果把m_obArray设为CXXDOC的成员变量则

  1. int ncount=m_obArray.GetSize();  
  2.     for(int i=0;i
  3.     {  
  4.         delete m_obArray.GetAt(i);  
  5.           
  6.     }  
  7.     m_obArray.RemoveAll();  


至此,整个笔记完成。谢谢

http://blog.csdn.net/zh634455283/article/details/7882897

阅读(3901) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~