【MFC】文档操作——范例(12)

使用MFC框架文档操作范例:

 创建工程

创建工程,其中:

1、MFC单文档

2、自定义改应用程序数据文件扩展名:

 

3、 最后一步选择CListView(用报表显示数据)

 重点问题:数据文件的读写功能

添加数据类

学生类,如下:

#pragma once
class CStudent
{
public:
	CStudent(void);
	~CStudent(void);
	virtual void Serialize(CArchive& ar);
	CString name;
	CString department;
	CString major;
	CString grade;
	CString classname;
	CString cid;
};

#include "stdafx.h"
#include "Student.h"


CStudent::CStudent(void)
{
}


CStudent::~CStudent(void)
{
}
void CStudent::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{	// storing code
		ar<<name<<department<<major<<grade<<classname<<cid;
	}
	else
	{	// loading code
		ar>>name>>department>>major>>grade>>classname>>cid;
	}
}

文档类:


// MFC05Doc.h : CMFC05Doc 类的接口
//


#pragma once
#include "Student.h"
#include <vector>
using namespace std;

class CMFC05Doc : public CDocument
{
protected: // 仅从序列化创建
	CMFC05Doc();
	DECLARE_DYNCREATE(CMFC05Doc)

// 特性
public:	
	vector<CStudent> svect;
// 操作
public:

// 重写
public:
	virtual BOOL OnNewDocument();
	virtual void Serialize(CArchive& ar);
#ifdef SHARED_HANDLERS
	virtual void InitializeSearchContent();
	virtual void OnDrawThumbnail(CDC& dc, LPRECT lprcBounds);
#endif // SHARED_HANDLERS

// 实现
public:
	virtual ~CMFC05Doc();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// 生成的消息映射函数
protected:
	DECLARE_MESSAGE_MAP()

#ifdef SHARED_HANDLERS
	// 用于为搜索处理程序设置搜索内容的 Helper 函数
	void SetSearchContent(const CString& value);
#endif // SHARED_HANDLERS
public:
	afx_msg void OnAddStu();
//	virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
};

其中 :  vector<CStudent> svect;   即保存多个学生信息的向量(STL)

资源视图中添加菜单命令:

添加对话框(用于添加学生)

 

文档类中响应菜单命令,并且打开对话框:

 代码如下:


// MFC05Doc.cpp : CMFC05Doc 类的实现
//

#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "MFC05.h"
#endif

#include "MFC05Doc.h"

#include <propkey.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CMFC05Doc

#include "AddStuDlg.h"
IMPLEMENT_DYNCREATE(CMFC05Doc, CDocument)

BEGIN_MESSAGE_MAP(CMFC05Doc, CDocument)
	ON_COMMAND(IDC_ADD_STU, &CMFC05Doc::OnAddStu)
END_MESSAGE_MAP()


// CMFC05Doc 构造/析构

CMFC05Doc::CMFC05Doc()
{
	// TODO: 在此添加一次性构造代码

}

CMFC05Doc::~CMFC05Doc()
{
}

BOOL CMFC05Doc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: 在此添加重新初始化代码
	// (SDI 文档将重用该文档)
	svect.clear();
	return TRUE;
}




// CMFC05Doc 序列化

void CMFC05Doc::Serialize(CArchive& ar)
{
	int size;
	if (ar.IsStoring())
	{
		// TODO: 在此添加存储代码
		size=svect.size();
		ar<<size;
		for(int i=0;i<size;i++)
			svect[i].Serialize(ar);
	}
	else
	{
		// TODO: 在此添加加载代码
		ar>>size;
		for(int i=0;i<size;i++)
		{
			CStudent s;
			s.Serialize(ar);
            svect.push_back(s);
		}
			
	}
}

#ifdef SHARED_HANDLERS

// 缩略图的支持
void CMFC05Doc::OnDrawThumbnail(CDC& dc, LPRECT lprcBounds)
{
	// 修改此代码以绘制文档数据
	dc.FillSolidRect(lprcBounds, RGB(255, 255, 255));

	CString strText = _T("TODO: implement thumbnail drawing here");
	LOGFONT lf;

	CFont* pDefaultGUIFont = CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT));
	pDefaultGUIFont->GetLogFont(&lf);
	lf.lfHeight = 36;

	CFont fontDraw;
	fontDraw.CreateFontIndirect(&lf);

	CFont* pOldFont = dc.SelectObject(&fontDraw);
	dc.DrawText(strText, lprcBounds, DT_CENTER | DT_WORDBREAK);
	dc.SelectObject(pOldFont);
}

// 搜索处理程序的支持
void CMFC05Doc::InitializeSearchContent()
{
	CString strSearchContent;
	// 从文档数据设置搜索内容。
	// 内容部分应由“;”分隔

	// 例如:  strSearchContent = _T("point;rectangle;circle;ole object;");
	SetSearchContent(strSearchContent);
}

void CMFC05Doc::SetSearchContent(const CString& value)
{
	if (value.IsEmpty())
	{
		RemoveChunk(PKEY_Search_Contents.fmtid, PKEY_Search_Contents.pid);
	}
	else
	{
		CMFCFilterChunkValueImpl *pChunk = NULL;
		ATLTRY(pChunk = new CMFCFilterChunkValueImpl);
		if (pChunk != NULL)
		{
			pChunk->SetTextValue(PKEY_Search_Contents, value, CHUNK_TEXT);
			SetChunkValue(pChunk);
		}
	}
}

#endif // SHARED_HANDLERS

// CMFC05Doc 诊断

#ifdef _DEBUG
void CMFC05Doc::AssertValid() const
{
	CDocument::AssertValid();
}

void CMFC05Doc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG


// CMFC05Doc 命令


void CMFC05Doc::OnAddStu()
{
	// TODO: 在此添加命令处理程序代码
	CAddStuDlg dlg;
	if(dlg.DoModal()==IDOK)
	{
		CStudent stu;
		stu.cid=dlg.m_cid;
		stu.classname=dlg.m_classname;
		stu.department=dlg.m_department;
		stu.grade=dlg.m_grade;
		stu.major=dlg.m_major;
		stu.name=dlg.m_name;
		svect.push_back(stu);
		this->UpdateAllViews(NULL);
		this->SetModifiedFlag();
	}
}

核心代码:

1、序列化函数,Serialize

思路:保存的时候,先写入学生个数,然后一个个写,读取的时候正好相反.。CStudent的序列化函数需要好好了解一下;

2、菜单命令响应:

打开对话框,读取添加的数据,新生成一个CStudent,添加到Vector,并且更新视图和设置文档已经修改标记(提醒保存)。

视图类相对比较简单:


// MFC05View.h : CMFC05View 类的接口
//

#pragma once


class CMFC05View : public CListView
{
protected: // 仅从序列化创建
	CMFC05View();
	DECLARE_DYNCREATE(CMFC05View)

// 特性
public:
	CMFC05Doc* GetDocument() const;

// 操作
public:

// 重写
public:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	bool isInitView;
	void InitView();
	void InitData();
protected:
	virtual void OnInitialUpdate(); // 构造后第一次调用

// 实现
public:
	virtual ~CMFC05View();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// 生成的消息映射函数
protected:
	DECLARE_MESSAGE_MAP()
public:
//	afx_msg void OnPaint();
//	afx_msg void OnSize(UINT nType, int cx, int cy);
//	virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/);
//	virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/);
//	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/);
};

#ifndef _DEBUG  // MFC05View.cpp 中的调试版本
inline CMFC05Doc* CMFC05View::GetDocument() const
   { return reinterpret_cast<CMFC05Doc*>(m_pDocument); }
#endif


// MFC05View.cpp : CMFC05View 类的实现
//

#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "MFC05.h"
#endif

#include "MFC05Doc.h"
#include "MFC05View.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMFC05View

IMPLEMENT_DYNCREATE(CMFC05View, CListView)

BEGIN_MESSAGE_MAP(CMFC05View, CListView)
//	ON_WM_SIZE()
END_MESSAGE_MAP()

// CMFC05View 构造/析构

CMFC05View::CMFC05View()
{
	// TODO: 在此处添加构造代码
	isInitView=false;

}

CMFC05View::~CMFC05View()
{
}

BOOL CMFC05View::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CListView::PreCreateWindow(cs);
}

void CMFC05View::OnInitialUpdate()
{
	CListView::OnInitialUpdate();
	if(!isInitView)	InitView();
	InitData();
}
void CMFC05View::InitView()
{
	CListCtrl& m_list = GetListCtrl();//得到内置的listctrl引用
	LONG lStyle;
	lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口风格
	lStyle |= LVS_REPORT; //设置报表风格
	SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle); //设置窗口风格
	CRect rect;
	m_list.GetClientRect(&rect);
	int cx =rect.Width()/8;
	m_list.InsertColumn( 0, " ", LVCFMT_CENTER, 50 );
	m_list.InsertColumn( 1, "姓名", LVCFMT_CENTER, cx );
	m_list.InsertColumn( 2, "学号", LVCFMT_CENTER, cx );
	m_list.InsertColumn( 3, "系部", LVCFMT_CENTER, cx );
	m_list.InsertColumn( 4, "专业", LVCFMT_CENTER, cx );
	m_list.InsertColumn( 5, "年级", LVCFMT_CENTER, cx );
	m_list.InsertColumn( 6, "班级", LVCFMT_CENTER, cx );
	m_list.InsertColumn( 7, "备注", LVCFMT_CENTER, 2*cx- 50);
	isInitView=true;
}
void CMFC05View::InitData()
{	
	CListCtrl& m_list = GetListCtrl();
	m_list.DeleteAllItems();
	vector<CStudent> svect=GetDocument()->svect;
	for(int i=0;i<svect.size();i++)
	{
		CString cs;
		cs.Format("%d",i+1);
		int row=m_list.InsertItem(i, "");
		m_list.SetItemText(row, 0, cs);
		m_list.SetItemText(row, 1, svect[i].name);
		m_list.SetItemText(row, 2, svect[i].cid);
		m_list.SetItemText(row, 3, svect[i].department);
		m_list.SetItemText(row, 4, svect[i].major);
		m_list.SetItemText(row, 5, svect[i].grade);
		m_list.SetItemText(row, 6, svect[i].classname);
		m_list.SetItemText(row, 7, "");
	}
}

// CMFC05View 诊断

#ifdef _DEBUG
void CMFC05View::AssertValid() const
{
	CListView::AssertValid();
}

void CMFC05View::Dump(CDumpContext& dc) const
{
	CListView::Dump(dc);
}

CMFC05Doc* CMFC05View::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFC05Doc)));
	return (CMFC05Doc*)m_pDocument;
}
#endif //_DEBUG




void CMFC05View::OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/)
{
	// TODO: 在此添加专用代码和/或调用基类
	InitData();
}

总结:

1、MFC提供的文档操作框架简化了文件操作,核心是序列化处理数据,由文档类去调用用户自定义的序列化函数,实现特定数据的读写;

2、MFC屏蔽了文件的操作和消息响应,结论是读写文件都会自动调用文档类的Serialize函数,具体流程可以通过跟踪调试去了解(应用程序类首先响应打开、新建、保存文档的消息!)

3、重点掌握三口组(文档、视图、框架)以及应用程序类之间的相互调用:

获取应用程序对象指针:::AfxGetApp()   全局函数  可以强制转换

获取主框架指针:::AfxGetMainWnd()  或者 ::AfxGetApp()->m_pMainWnd;  可以强制转换

视图获取文档:GetDocument() (框架提供)

视图获取主框架还可以:GetParentFrame()  可以强制转换

文档类获取视图:多视图需要枚举(比如窗口分割后多块显示同一个文档)

​
 POSITION pos=CDocument::GetFirstViewPosition();
        while(pos != NULL)
        {
            CView *pView=CDocument::GetNextView(pos);
            if(pView->GetRuntimeClass()==RUNTIME_CLASS(C**View))
            {
                

            }
        }

​

单视图可以按框架方法来完成。

框架获取视图:

单文档单视图  GetActiveView()

多视图:先获取文档指针 GetActiveDocument() ,然后 枚举(见上)。

4、MFC文档操作相对比较简单安全,当然也可以自己通过CFile等相关类来实现数据文档的操作。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
您可以使用 MFC 中的文档视图架构来保存当前操作。以下是保存当前操作的一般步骤: 1. 在您的文档类中添加一个成员变量,用于存储当前操作的数据。假设您要保存的数据是一个字符串,可以在文档类头文件中添加如下代码: ``` CString m_CurrentData; ``` 2. 在文档类的 `Serialize` 函数中,根据需要,添加保存和加载数据的代码。`Serialize` 函数会在保存和加载文档时被调用。例如,要保存和加载字符串数据,您可以在 `Serialize` 函数中添加如下代码: ``` void CMyDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { ar << m_CurrentData; } else { ar >> m_CurrentData; } } ``` 3. 在您的视图类或对应的对话框类中,添加保存和加载数据的 UI 元素,例如按钮或菜单项。 4. 在保存按钮或菜单项的响应函数中,调用文档对象的 `OnSaveDocument` 函数来保存文档。例如,在视图类中添加一个保存按钮,并在按钮的响应函数中添加以下代码: ``` void CMyView::OnSave() { CMyDoc* pDoc = GetDocument(); pDoc->OnSaveDocument(_T("yourfile.txt")); } ``` 5. 在加载按钮或菜单项的响应函数中,调用文档对象的 `OnOpenDocument` 函数来加载文档。例如,在视图类中添加一个加载按钮,并在按钮的响应函数中添加以下代码: ``` void CMyView::OnLoad() { CMyDoc* pDoc = GetDocument(); pDoc->OnOpenDocument(_T("yourfile.txt")); UpdateView(); // 更新视图以显示加载的数据 } ``` 请注意,上述代码中的 "yourfile.txt" 是保存和加载文件的路径和名称,请根据实际情况进行修改。 这是一个简单的示例,您可以根据您的具体需求进行更复杂的操作和错误处理。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

易老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值