`

[置顶] MFC(文档和串行化,孙鑫C++第十三讲笔记整理)

 
阅读更多

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("http://www.sunxin.org");

 ar<<i<<ch<<f<<str;以上是保存,打开略

 

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<nCount;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讲的文件操作内容:

void CWenDangView::OnXieru() 
{
	// TODO: Add your command handler code here

	CFile file("demo110.txt",CFile::modeCreate|CFile::modeWrite);
	CArchive ar(&file,CArchive::store);
	ar.Write("hello,use CArchive to show",strlen("hello,use CArchive to show"));
	ar.Close();

	//用下面这种方式的话,如果运行程序没有关闭的话,txt文档打不开,会报错说该文件正在使用
	//CFile *file=new CFile("demo111.txt",CFile::modeCreate|CFile::modeWrite);
	//CArchive ar(file,CArchive::store);
	

}


 

void CWenDangView::OnDuqu() 
{
	// TODO: Add your command handler code here

	/*CFile file("demo110.txt",CFile::modeRead);
	CArchive ar(&file,CArchive::load);
	char ch[100];
	memset(ch,0,100);
	ar.Read(ch,100);
	MessageBox(ch);*/

	//或者使用这种方式:
	CFile file("demo110.txt",CFile::modeRead);
	CArchive ar(&file,CArchive::load);
	int len=file.GetLength();
	char *ch=new char[len+1];
	ar.Read(ch,len);
	ch[len]=0;
	MessageBox(ch);
	
}


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

SetTitle("hello,CDocument");


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

 

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

 

 

OnXieRu

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


OnDuQu

CFile file("demo111.txt",CFile::modeRead);
	CArchive ar(&file,CArchive::load);
	int a;
	char b;
	float d;
	CString cstring;
	CString result;
	ar>>a>>b>>d>>cstring;
	result.Format("%d,%c,%f,%s",a,b,d,cstring);
	MessageBox(result);
	ar.Close();

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

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

void CWenDangDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}


 

void CWenDangDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here

		CFile file("demo112.txt",CFile::modeCreate|CFile::modeWrite);
		CArchive ar(&file,CArchive::store);
		int a=10086;
		CString cstring="hello,VC++";
		
		ar<<a<<cstring;
		ar.Close();
	}
	else
	{
		// TODO: add loading code here
		CFile file("demo112.txt",CFile::modeRead);
		CArchive ar(&file,CArchive::load);
		int a;
		CString cstring;
		CString result;

		ar>>a>>cstring;
		result.Format("%d,%s",a,cstring);
		AfxMessageBox(result);
		ar.Close();

	}
}


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

 

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

 

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

步骤1

class HuiTu  :public CObject
{
public:
	HuiTu();
	virtual ~HuiTu();

public:
	CPoint yuandian;
	CPoint zhondian;
	UINT leixing;

};


步骤2

public:
	HuiTu();
	virtual ~HuiTu();
	void Serialize(CArchive& ar);
void HuiTu::Serialize(CArchive& ar)
{
	if(ar.IsStoring())
	{
		ar<<leixing<<yuandian<<zhondian;
	}
	else
	{
		ar>>leixing>>yuandian>>zhondian;

	}
}


步骤3

class HuiTu  :public CObject
{
	DECLARE_SERIAL(HuiTu)

public:
	HuiTu();
	virtual ~HuiTu();
	void Serialize(CArchive& ar);

public:
	CPoint yuandian;
	CPoint zhondian;
	UINT leixing;

};


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

步骤5

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

IMPLEMENT_SERIAL( HuiTu, CObject, 1 )


这样 五个条件就完成了

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

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

void HuiTu::Draw(CDC *pdc)
{
	CBrush *newbrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
	CBrush *oldbrush=pdc->SelectObject(newbrush);

	switch(leixing)
	{
	case 1:
		pdc->SetPixel(zhondian,RGB(0,0,0));
		break;

	case 2:
		pdc->MoveTo(yuandian);
		pdc->LineTo(zhondian);
		break;
	case 3:
		pdc->Rectangle(&CRect(yuandian,zhondian));
		break;
	case 4:
		pdc->Ellipse(&CRect(yuandian,zhondian));
		break;
	default:
		break;

	}
}


菜单响应函数

void CWenDangView::OnDian() 
{
	// TODO: Add your command handler code here
	leixing=1;
}

void CWenDangView::OnXian() 
{
	// TODO: Add your command handler code here
	leixing=2;
}

void CWenDangView::OnJuxing() 
{
	// TODO: Add your command handler code here
	leixing=3;
}

void CWenDangView::OnTuoyuan() 
{
	// TODO: Add your command handler code here
	leixing=4;
}


void CWenDangView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default

	m_zhondian=point;

	CClientDC ccdc(this);
	CBrush *newbrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));

	switch(m_leixing){
	case 1:
		ccdc.SetPixel(m_yuandian,RGB(0,0,0));
		break;
		
	case 2:
		ccdc.MoveTo(m_yuandian);
		ccdc.LineTo(point);
		break;
	case 3:
		ccdc.Rectangle(&CRect(m_yuandian,point));
		break;
	case 4:
		ccdc.Ellipse(&CRect(m_yuandian,point));
		break;
	default:
		break;
	}
	
	HuiTu *huitu;
	huitu=new HuiTu(m_leixing,m_yuandian,point);
	m_obArray.Add(huitu);


	CView::OnLButtonUp(nFlags, point);
}


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

void CWenDangDoc::Serialize(CArchive& ar)
{

	POSITION position=GetFirstViewPosition();
	CWenDangView *wendangview=(CWenDangView*)GetNextView(position);

	if (ar.IsStoring())
	{
		// TODO: add storing code here

		/*CFile file("demo112.txt",CFile::modeCreate|CFile::modeWrite);
		CArchive ar(&file,CArchive::store);
		int a=10086;
		CString cstring="hello,VC++";
		
		ar<<a<<cstring;
		ar.Close();*/

		int ncount=wendangview->m_obArray.GetSize();
		ar<<ncount;
		for(int i=0;i<ncount;++i)
		{
			ar<<wendangview->m_obArray.GetAt(i);
		}
		


	}
	else
	{
		// TODO: add loading code here
		/*CFile file("demo112.txt",CFile::modeRead);
		CArchive ar(&file,CArchive::load);
		int a;
		CString cstring;
		CString result;

		ar>>a>>cstring;
		result.Format("%d,%s",a,cstring);
		AfxMessageBox(result);
		ar.Close();*/

		int ncount;
		ar>>ncount;//先存先取

		HuiTu *huitu;
		for(int i=0;i<ncount;++i)
		{
			ar>>huitu;
			wendangview->m_obArray.Add(huitu);
		}



	}
	//wendangview->m_obArray.Serialize(ar);
}


 

 

void CWenDangView::OnDraw(CDC* pDC)
{
	CWenDangDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	int ncount=m_obArray.GetSize();
	for(int i=0;i<ncount;++i)
	{
		((HuiTu*)m_obArray.GetAt(i))->Draw(pDC);
	}
	
	// TODO: add draw code for native data here
}

 

因为CObArray支持Serialize

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

void CWenDangDoc::Serialize(CArchive& ar)
{

	POSITION position=GetFirstViewPosition();
	CWenDangView *wendangview=(CWenDangView*)GetNextView(position);

	if (ar.IsStoring())
	{
		// TODO: add storing code here

	}
	else
	{
		
            // TODO: add storing code here
	}
	wendangview->m_obArray.Serialize(ar);//本身支持这个操作
}


最好把数据都放在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虚函数,文档新建或销毁的时候会调用

void CWenDangDoc::DeleteContents() 
{
	// TODO: Add your specialized code here and/or call the base class
	
	POSITION pos=GetFirstViewPosition();
	CWenDangView *wendangview=(CWenDangView*)GetNextView(pos);

	int ncount=wendangview->m_obArray.GetSize();
	for(int i=0;i<ncount;++i)
	{
		delete wendangview->m_obArray.GetAt(i);
		//wendangview->m_obArray.RemoveAt(i);//这里每删除一次,编号都会跟着改变的,这里会发生内存泄漏
	}
	wendangview->m_obArray.RemoveAll();

	CDocument::DeleteContents();
}


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

int ncount=m_obArray.GetSize();
	for(int i=0;i<ncount;++i)
	{
		delete m_obArray.GetAt(i);
		
	}
	m_obArray.RemoveAll();


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


 


 

更多详细信息请查看java教程网 http://www.itchm.com/forum-59-1.html
分享到:
评论

相关推荐

    孙鑫C++教程(全20讲)PPT讲义源码及电子书

    第十三课:文档与串行化 第十四课:网络相关知识 第十五课:多线程与聊天室程序的创建 第十六课:线程同步与异步套接字编程 第十七课:进程间通信 第十八课:ActiveX控件 第十九课:动态链接库 第二十课:HOOK和数据库访问 ...

    孙鑫C++教程(全20讲)PPT讲义及代码.zip

    《孙鑫C++教程(全20讲)PPT讲义及代码.zip》是一份针对初学者的C++编程教程,旨在帮助零基础的学员掌握C++编程语言的基础知识和核心概念。这份教程包含了20个章节的完整内容,通过PPT讲义和配套代码,为学习者提供了...

    孙鑫C++教程(全20讲)PPT讲义.rar

    《孙鑫C++教程(全20讲)PPT讲义》是一套全面且深入的C++学习资源,由知名编程教育专家孙鑫精心编撰。这套教程通过20个独立的讲座,覆盖了C++语言的核心概念、语法以及高级特性,旨在帮助初学者和有一定基础的程序员...

    孙鑫 c++ 视频个人总结

    而在处理`WM_PAINT`消息时,`BeginPaint`和`EndPaint`函数用于初始化和结束绘画操作,`TextOut`函数再次被用来绘制文本,这展示了基本的用户界面元素的绘制方法。 此外,学习C++不仅仅是学习语法,还包括理解数据...

    孙鑫C++教程(全20讲)PPT讲义

    《孙鑫C++教程(全20讲)PPT讲义》是一套全面且深入的C++学习资源,由知名编程讲师孙鑫精心编撰。本教程覆盖了C++语言的基础到高级概念,旨在帮助初学者及有经验的开发者巩固和提升C++编程技能。 在C++这个强大的面向...

    孙鑫MFC全套程序,基于vs2015

    例如,L1可能代表第一课,介绍MFC的基本概念和创建第一个MFC工程;L6可能涉及窗口及控件的事件处理;L16可能讲解了MFC中的类层次结构及其应用。 在学习和实践中,开发者需要掌握MFC的消息映射机制,这是MFC处理用户...

    孙鑫MFC完整笔记.pdf

    孙鑫pdf文档,入门C++的好帮手,MFC类库,vc6.0,虽然版本比较老,但是在很多地方使用得仍然比较多。参考性大

    孙鑫C++教程(全20讲)PPT讲义和源代码.rar

    《孙鑫C++教程》是一套深受初学者欢迎的C++教学资源,包含了全面的20讲内容,旨在帮助新手逐步掌握这门强大的编程语言。本教程由知名讲师孙鑫精心编写,以其深入浅出的教学风格,使得复杂的编程概念变得易于理解。 ...

    孙鑫C++教程(全20讲)PPT讲义-11-20.rar

    3. **第13讲:继承与多态** 继承是OOP中的另一个关键特性,允许一个类(子类)继承另一个类(父类)的属性和行为。多态则允许不同类型的对象对同一消息作出不同的响应,通常通过虚函数实现。这为代码的重用和扩展...

    孙鑫C++教程(全20讲)PPT讲义

    【孙鑫C++教程(全20讲)PPT讲义】是一套全面且深入的C++学习资源,由知名讲师孙鑫倾力打造。这套教程不仅覆盖了C++的基础语法,还包括了高级特性和实战应用,旨在帮助学习者从入门到精通。尽管该教程的年代稍显久远...

    孙鑫 VC++ 深入详解书中源码

    《孙鑫 VC++ 深入详解》是一本深受程序员喜爱的VC++技术书籍,作者孙鑫以其深入浅出的讲解方式,详细剖析了VC++的底层机制和高级特性。书中的源码是理解理论知识的关键实践部分,通过分析和运行这些代码,读者可以更...

    孙鑫C++教程(全20讲)PPT讲义.21M

    《孙鑫C++教程》是一套全面且深入的C++学习资源,共计20讲,包含PPT讲义,旨在帮助学习者掌握这门强大的编程语言。本教程因其高质量的内容和实用性,被誉为C++领域中的优秀软件教程。下面将详细阐述C++语言的基础...

    孙鑫C++教程(全20讲)PPT讲义 + code

     编程语言枯燥难懂,然而通过孙鑫老师形象化的讲解,Windows和MFC编程中的难点、重点,让你轻松掌握。 3、实战性强  编程中要注意什么?如何阅读出错提示?如何调试运行程序?如何排查错误,解决问题?通过孙鑫...

    孙鑫C++教程(全20讲)PPT讲义.ppt

    "孙鑫C++教程(全20讲)PPT讲义.ppt" titular description: 本资源是一份孙鑫的C++教程的PPT讲义,全20讲,涵盖了C++语言的基础知识和高级应用。讲义中包含了windows程序的内部运行原理、API的概念、消息机制、句柄...

    VC深入详解(孙鑫笔记)自学必备

    《VC深入详解(孙鑫笔记)自学必备》是面向初学者和进阶者的一份珍贵资料,由知名IT专家孙鑫编撰。这份文档详细介绍了Microsoft Visual C++(简称VC)的相关知识,涵盖了从基本概念到高级编程技巧的广泛内容。通过这份...

    MFC资料(技术文档/PPT/图书).rar

    MFC提供了资源管理功能,通过.rc文件和MFC的资源类,可以实现应用程序的国际化和本地化,支持多种语言。 10. **调试与性能优化** MFC包含了一些辅助调试的类,如CFileTrace,帮助开发者跟踪文件操作。同时,MFC...

    MFC C++讲义

    《孙鑫C++教程(全20讲)PPT讲义》可能是这份资料的配套教学材料,其中可能包含了丰富的实例和逐步解释,帮助学习者更好地理解和实践MFC编程。通过深入学习和实践这些内容,你将能够熟练掌握MFC,从而高效地开发...

    vc++PPT讲义和mfc教程及c++入门基础讲解

    该资源由内附孙鑫讲解的vc++编程1-20课的PPT讲解和详细实现代码,另附c++入门基础的课程,是每位c++编程爱好者必学的课程资源c++编程进阶的必经之路。

    C++深入详解自学笔记

    第十三课文档串行化,是关于数据持久化存储的技术,它允许程序将数据保存到文件并在需要时恢复,这对于保存用户设置或游戏进度等场景非常实用。 第十四课和十五课涉及网络编程,包括基础的TCP/IP通信和多线程技术。...

    精通MFC程序设计

    最后,我们还将学习如何使用MFC进行调试、性能优化和国际化本地化,这些都是提高软件质量和用户体验的重要环节。通过本教程的学习,你将能够自信地使用MFC进行复杂的Windows应用程序设计,无论是桌面应用还是企业级...

Global site tag (gtag.js) - Google Analytics