MFC:文件

<span style="font-size:18px;">
</span>
<span style="font-size:18px;">
</span>
<span style="font-size:18px;">知识点补充:
1、指向常量的指针:char ch[5] = "list"; const char* pStr = ch;
pStr指向的内容不可改变,pStr的指针值可以改变:
*pStr = 'w';//error    pStr = "vector";//ok
2、指针常量:char ch[5] = "list"; char* const pStr = ch;
指针本身是常量,指向的内容可以修改,指针值不可修改:
pStr = "love";//error    *pStr = 'w';//ok
/***********************************************************************************************/
当按照文本方式向文件中写入数据时,若遇到换行字符(ASCII为10),会转换为回车换行(ASCII为13,10)。在读取文件时,若遇到
回车换行的组合(即连续的ASCII 13、10),则会转换为换行字符(ASCII为10)。//以文本方式写入和以二进制方式读会差一个字符:
当以二进制方式向文件中写入数据时,将数据在内存中的存储形式原样输出到文件中.所以读取写入数据的方式应该一致.
//C、C++、MFC读写文件及MFC打开保存文件对话框:
void CFileView::OnFileWrite() 
{
/*	FILE *pFile=fopen("1.txt","w");//c语言使用了缓冲文件系统
	fwrite("file",1,strlen("file"),pFile);//写入了缓冲区中,缓冲区满后才写/读入磁盘文件
	//fseek(pFile,0,SEEK_SET); //将文件内部指针移到文件开始位置
	//fwrite("ftp:",1,strlen("ftp:"),pFile);
	//fwrite("file",1,strlen("file"),pFile);
	fclose(pFile);*/  //将缓冲区中的数据写入磁盘文件
	//fflush(pFile); //刷新缓冲区,把数据写入文件,而不必关闭文件
/*	FILE *pFile=fopen("2.txt","wb");//以二进制方式打开
	char ch[3];
	ch[0]='a';
	ch[1]=10; //换行(存放的是ASCII)
	ch[2]='b';
	fwrite(ch,1,3,pFile);
	fclose(pFile);*/
	/*FILE *pFile=fopen("3.txt","w");
	int i=98341;//将98341以整数方式写入?打开时显示98341
	char ch[5];*/
	/*ch[0]=9+48;//法一:以ASCII形式写入,和内存一致
	ch[1]=8+48;
	ch[2]=3+48;
	ch[3]=4+48;
	ch[4]=1+48;*/
	/*itoa(i,ch,10);//法二:将数字转换为字符串写入
	//fwrite(&i,4,1,pFile);
	fwrite(ch,1,5,pFile);
	fclose(pFile);*/
/*	ofstream ofs("4.txt");   //C++语法,需包含头文件
	ofs.write("file",strlen("file"));
	ofs.close();  */
/*	HANDLE hFile;
	hFile=CreateFile("5.txt",GENERIC_WRITE,0,NULL,CREATE_NEW,
		FILE_ATTRIBUTE_NORMAL,NULL); //win32 AIP函数
	DWORD dwWrites;
	WriteFile(hFile,"file",strlen("file"),
		&dwWrites,NULL);     //写文件
	CloseHandle(hFile);  */
/*	CFile file("6.txt",CFile::modeCreate | CFile::modeWrite); //MFC提供
	file.Write("file",strlen("file"));
	file.Close();*/
	CFileDialog fileDlg(FALSE);
	fileDlg.m_ofn.lpstrTitle="我的文件保存对话框";
	fileDlg.m_ofn.lpstrFilter="Text Files(*.txt)\0*.txt\0All Files(*.*)\0*.*\0\0";
	fileDlg.m_ofn.lpstrDefExt="txt";
	if(IDOK==fileDlg.DoModal())
	{
		CFile file(fileDlg.GetFileName(),CFile::modeCreate | CFile::modeWrite);
		file.Write("file",strlen("file"));
		file.Close();
	}
}
void CFileView::OnFileRead() 
{
/*	FILE *pFile=fopen("1.txt","r");//以文本方式打开
//	char ch[100];
//	memset(ch,0,100);
//	fread(ch,1,100,pFile);
//	MessageBox(ch);
	char *pBuf;
	fseek(pFile,0,SEEK_END); //文件内部指针移到文件结尾
	int len=ftell(pFile); //得到文件内部指针的当前位置
	pBuf=new char[len+1];
	rewind(pFile); //重新放置文件内部指针到文件开始处
	fread(pBuf,1,len,pFile);
	pBuf[len]=0;
	MessageBox(pBuf);
	fclose(pFile);  */
/*	FILE *pFile=fopen("2.txt","rb");//以二进制方式打开
	char ch[100];
	fread(ch,1,3,pFile);
	ch[3]=0;
	MessageBox(ch);
	fclose(pFile);  */
/*	ifstream ifs("4.txt"); //C++语法,需包含头文件
	char ch[100];
	memset(ch,0,100);
	ifs.read(ch,100);
	ifs.close();
	MessageBox(ch);  */
/*	HANDLE hFile;
	hFile=CreateFile("5.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,NULL); //win32 API函数
	char ch[100];
	DWORD dwReads;
	ReadFile(hFile,ch,100,&dwReads,NULL); //读文件
	ch[dwReads]=0;
	CloseHandle(hFile); //关闭文件句柄
	MessageBox(ch);  */
/*	CFile file("6.txt",CFile::modeRead); //MFC提供
	char *pBuf;
	DWORD dwFileLen;
	dwFileLen=file.GetLength();
	pBuf=new char[dwFileLen+1];
	pBuf[dwFileLen]=0;
	file.Read(pBuf,dwFileLen);
	file.Close();
	MessageBox(pBuf);  */
	CFileDialog fileDlg(TRUE);
	fileDlg.m_ofn.lpstrTitle="我的文件打开对话框";
	fileDlg.m_ofn.lpstrFilter="Text Files(*.txt)\0*.txt\0All Files(*.*)\0*.*\0\0";
	if(IDOK==fileDlg.DoModal())
	{
		CFile file(fileDlg.GetFileName(),CFile::modeRead);
		char *pBuf;
		DWORD dwFileLen;
		dwFileLen=file.GetLength();
		pBuf=new char[dwFileLen+1];
		pBuf[dwFileLen]=0;
		file.Read(pBuf,dwFileLen);
		file.Close();
		MessageBox(pBuf);
	}
}
/***********************************************************************************************/
//兼容16位版本,存储信息在WIN.INI文件中(InitInstance中添加):
/*	::WriteProfileString("love","admin","zhangsan");//表项,键名,值
	CString str;
	::GetProfileString("love","admin","lisi",
		str.GetBuffer(100),100); //若修改字符串,之后需调用ReleaseBuffer
	AfxMessageBox(str); */
/*	WriteProfileString("love","admin","zhangsan"); //写入的是注册表中(App继承的)
	CString str;
	str=GetProfileString("love","admin");
	AfxMessageBox(str); */
//读写注册表:
void CFileView::OnRegWrite() //写注册表
{
	HKEY hKey;
	DWORD dwAge=20;
	RegCreateKey(HKEY_LOCAL_MACHINE,"Software\\http://www.kai.org\\admin",&hKey); //创建注册表项,若存在,打开
	RegSetValue(hKey,NULL,REG_SZ,"zhangsan",strlen("zhangsan"));//存储字符串类型
	RegSetValueEx(hKey,"age",0,REG_DWORD,(CONST BYTE*)&dwAge,4);//存储其他类型
	RegCloseKey(hKey);
}
void CFileView::OnRegRead() //读注册表
{
/*	LONG lValue;
	RegQueryValue(HKEY_LOCAL_MACHINE,"Software\\http://www.kai.org\\admin",
		NULL,&lValue); //LPTSTR置为NULL,得到数据长度存在lValue(包含终止的空字符)中
	char *pBuf=new char[lValue];
	RegQueryValue(HKEY_LOCAL_MACHINE,"Software\\http://www.kai.org\\admin",
		pBuf,&lValue);
	MessageBox(pBuf);*/
	HKEY hKey;
	RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\http://www.kai.org\\admin",&hKey);//打开注册表项
	DWORD dwType;
	DWORD dwValue;
	DWORD dwAge;
	RegQueryValueEx(hKey,"age",0,&dwType,(LPBYTE)&dwAge,&dwValue);//dwType:返回的数据类型
	CString str;
	str.Format("age=%d",dwAge);
	MessageBox(str);
}
/***********************************************************************************************/
文档串行化(CArchive,之前必须创建一个CFile对象):
//CArchive不仅可以处理基本类型,还可以处理CObject派生类
void CGraphic1View::OnArchive() 
{
	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("zhangyue");
	ar << i << ch << f << str;
}
void CGraphic1View::OnRead() 
{
	CFile file("1.txt",CFile::modeRead);
	CArchive ar(&file,CArchive::load);
	int i;
	char ch;
	float f = 0.0;
	CString str;
	CString strResult;
	ar >> i >> ch >> f >> str; //保存时是什么顺序,提取时也要是这个顺序
	strResult.Format("%d,%c,%f,%s",i,ch,f,str);
	MessageBox(strResult);
}
///
给文档添加标题:
法一:BOOL CGraphic1Doc::OnNewDocument(){ //文件-新建 会调用此函数.
	if (!CDocument::OnNewDocument())
		return FALSE;
	SetTitle("love");//在此设置文档标题
	return TRUE;
}//( CWinApp::OnFileNew(); CDocManager::OnFileNew()...)文档框架视图对象三位一体,都会创建
法二:在资源视图的String Table中的IDR_MAINFRAME的Caption中的第二个项输入标题名.
//那么,资源视图中的字符创、菜单、图标等资源何时加入程序中了呢?
//在App类的InitInstance()函数中,有下面所示代码,将文档框架视图关联在一起:
	CSingleDocTemplate* pDocTemplate;   //构造了一个单文档模板对象
	pDocTemplate = new CSingleDocTemplate(
			IDR_MAINFRAME, //资源ID(包含多种资源)
			RUNTIME_CLASS(CGraphic1Doc),
			RUNTIME_CLASS(CMainFrame),   // main SDI frame window
			RUNTIME_CLASS(CGraphic1View));
	AddDocTemplate(pDocTemplate);
//对于IDR_MAINFRAME资源中的各个子串,可以利用CDocTemplate::GetDocString来获取:
virtual BOOL GetDocString( 
   CString& rString, 
   enum DocStringIndex index  
) const;
CDocTemplate::windowTitle //主窗口标题栏上的字符串;MDI不需指定,将一IDR_MAINFRAME串为默认值
CDocTemplate::docName   //缺省文档名,若没有指定,将为无标题
CDocTemplate::fileNewName  //文档类型的名称,若应用程序支持多种类型文档(增加另一个模板对象在InitInstance中),
			   //此串将显示在File/New对话框中
CDocTemplate::filterName  //出现在File/Open对话框中,要和filterExt一起使用 
CDocTemplate::filterExt  //文档缺省扩展名,若没有指定,就不能出现在打开对话框中,和filterName一起使用
CDocTemplate::regFileTypeId 
CDocTemplate::regFileTypeName 
///
在Doc类中有个函数:Serialize(CArchive &ar);
void CGraphic1Doc::Serialize(CArchive& ar) //文件-打开/保存对话框关闭后会调用此函数
{
	if (ar.IsStoring()){    // TODO: add storing code here
		int i = 4;
		char ch = 'a';
		float f = 1.3f;
		CString str("zhangyue");
		ar << i << ch << f << str;
	}
	else{             // TODO: add loading code here
		int i;
		char ch;
		float f = 0.0;
		CString str;
		CString strResult;
		ar >> i >> ch >> f >> str; //保存时是什么顺序,提取时也要是这个顺序
		strResult.Format("%d,%c,%f,%s",i,ch,f,str);
		AfxMessageBox(strResult);//不是从CWnd派生的,用应用程序框架的函数
	}
}
///
创建一个串行化的类(支持串行化)需要5个步骤:
1、让你的类从CObject(或其派生类)中派生
2、重载Serialize成员函数
3、在类声明中使用DECLARE_SERIAL(类名)宏
4、添加一个不带参数的构造函数
5、INPLEMENT_SERIAL(类名,基类名,1)//1:版本号
//CDocument::GetFirstViewPosition(),GetNextView();
有关文件读写的操作在CDocument的Serialize函数中进行,有关数据和图形的显示在CView的OnDraw函数中进行;
在其派生类中,只需要去关注Serialize和OnDraw函数就可以了,其他细节不需要理会。
当按下File/Open,应用程序框架会激活文件打开对话框,让你指定文件名,然后自动调用CGraphicDoc::Serialize
读取文件;应用程序框架还会调用CGraphicView::OnDraw,传递一个DC,让你重新绘制窗口内容。
一个文档对象可以和多个视类对象相关联,而一个视类对象只能和一个文档对象相关联。
eg:
class CGraph:public CObject{.....}
void CGraph::Serialize(CArchive& ar)  //支持串行化的5个步骤
{
	if(ar.IsStoring())
	{
		ar<<m_nDrawType<<m_ptOrigin<<m_ptEnd;
	}
	else
	{
		ar>>m_nDrawType>>m_ptOrigin>>m_ptEnd;
	}
}
CGraph::CGraph(UINT m_nDrawType,CPoint m_ptOrigin,CPoint m_ptEnd) //绘图类的构造函数存储绘图的必要东西
{
	this->m_nDrawType=m_nDrawType;
	this->m_ptOrigin=m_ptOrigin;
	this->m_ptEnd=m_ptEnd;
}
void CGraph::Draw(CDC *pDC)  //绘图类的窗口重绘函数
{
	CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
	CBrush *pOldBrush=pDC->SelectObject(pBrush);
	switch(m_nDrawType)
	{
	case 1:
		pDC->SetPixel(m_ptEnd,RGB(0,0,0));
		break;
	case 2:
		pDC->MoveTo(m_ptOrigin);
		pDC->LineTo(m_ptEnd);
		break;
	case 3:
		pDC->Rectangle(CRect(m_ptOrigin,m_ptEnd));
		break;
	case 4:
		pDC->Ellipse(CRect(m_ptOrigin,m_ptEnd));
		break;
	}
	pDC->SelectObject(pOldBrush);
}

void CGraphicDoc::Serialize(CArchive& ar)     // 文档类的Serialize函数
{
	POSITION pos=GetFirstViewPosition();
	CGraphicView *pView=(CGraphicView*)GetNextView(pos);
	if (ar.IsStoring()){  // TODO: add storing code here
/*		int nCount=pView->m_obArray.GetSize();
		ar<<nCount; //要存储在CObArray中的绘图种类
		for(int i=0;i<nCount;i++)
		{
			ar<<pView->m_obArray.GetAt(i);
		}    */
	}
	else{	// TODO: add loading code here
/*		int nCount;
		ar>>nCount;
		CGraph *pGraph;
		for(int i=0;i<nCount;i++)
		{
			ar>>pGraph;
			pView->m_obArray.Add(pGraph);
		}
	}    */
	m_obArray.Serialize(ar); //CObArray(其实是内部成员)也支持串行化
}
CGraphicDoc* CGraphicView::GetDocument(){...} //MFC提供
void CGraphicView::OnDraw(CDC* pDC)		//View类的重绘函数
{
	CGraphicDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	int nCount;
	nCount=pDoc->m_obArray.GetSize();
	for(int i=0;i<nCount;i++)
	{
		((CGraph*)m_obArray.GetAt(i))->Draw(pDC);
	}
}
void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point) //绘制完毕,把图形保存在CObArray中
{
	CClientDC dc(this);
	CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
	dc.SelectObject(pBrush);
	switch(m_nDrawType)
	{
	case 1:
		dc.SetPixel(point,RGB(0,0,0));
		break;
	case 2:
		dc.MoveTo(m_ptOrigin);
		dc.LineTo(point);
		break;
	case 3:
		dc.Rectangle(CRect(m_ptOrigin,point));
		break;
	case 4:
		dc.Ellipse(CRect(m_ptOrigin,point));
		break;
	}
	CGraph *pGraph=new CGraph(m_nDrawType,m_ptOrigin,point); //把绘制图形的必备变量传给CGraph类
	CGraphicDoc *pDoc=GetDocument(); //利用MFC框架得到文档类
	pDoc->m_obArray.Add(pGraph);
	CView::OnLButtonUp(nFlags, point);
} //pGraph指针没有释放!看后面的CGraphicDoc::DeleteContents函数

void CGraphicView::OnDraw(CDC* pDC)     //View类的窗口重绘函数
{
	CGraphicDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	int nCount;
	nCount=pDoc->m_obArray.GetSize();
	for(int i=0;i<nCount;i++)
	{
		((CGraph*)pDoc->m_obArray.GetAt(i))->Draw(pDC);
	}
}
//文件打开和新建都会调用此函数,所以在此释放在堆上申请的内存
void CGraphicDoc::DeleteContents() //虚函数,不会消除CDocument自身
{
	int nCount;
	nCount=m_obArray.GetSize();
	/*for(int i=0;i<nCount;i++)
	{
		delete m_obArray.GetAt(i);
		//m_obArray.RemoveAt(i);
	}//RemoveAt下移所有被移除元素上面的元素,并递减上界,但不释放内存
	m_obArray.RemoveAll();*/
	while(nCount--) //!!!!!!
	{
		delete m_obArray.GetAt(nCount);//只删了内存,没有删除指针自身
		m_obArray.RemoveAt(nCount);
	}
	CDocument::DeleteContents();
}

</span>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值