一、文档视图结构

文档类(CDocument):存储加载(读写)数据
视图类(CView):显示和修改数据

1)单文档

a)文档模板:把框架窗口、文档、视图关联在一起
b)文档类(CDocument):
OnNewDocument(),第一次新建窗口调用,后面每次按“新建”,自动调用此函数
DeleteContents(),做一些释放资源的操作,每次按“新建”,新建前先调用此函数
c)框架类可以认为是视图类的容器

测试多文档

    // 注册应用程序的文档模板。  文档模板
// 将用作文档、框架窗口和视图之间的连接
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_TestTYPE,
RUNTIME_CLASS(CTestDoc),
RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
RUNTIME_CLASS(CTestView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);

2)各类相关访问

文档视图各类之间相互访问

a) 在视图类,如何访问文档对象指针 CView::GetDocument
CDocument* GetDocument() const;

二、文档序列化(二进制操作文件 CArchive) 相当于Qt QDataStream

序列化:以二进制方式写文件
反序列化:以二进制方式读文件

1)写文件

a) 创建文件对象 CFile
b) 以写方式打开文件 CFile::Open
c) 创建序列化对象,并且和文件关联在一起 CArchive
CArchive::store 把数据保存到归档文件中。允许CFile写操作。
d) 往数据流写数据(相当于往文件写数据)
ar << a << b << c
e) 断开数据流和文件的关联 CArchive::Close
f) 关闭文件 CFile::Close

2)读文件

a) 创建文件对象 CFile
b) 以读方式打开文件 CFile::Open
c) 创建序列化对象,并且和文件关联在一起 CArchive
CArchive::load 从归档文件装载数据。CFile只读。
d) 往数流读数据(相当于往文件读数据)
ar >> a >> b >> c
e) 断开数据流和文件的关联 CArchive::Close
f) 关闭文件 CFile::Close

单文档建立mfc工程:

添加事件处理函数

// CMainFrame 消息处理程序

//写文件
void CMainFrame::OnArchiveWrite()
{
// TODO: 在此添加命令处理程序代码 /*
a) 创建文件对象 CFile
b) 以写方式打开文件 CFile::Open
c) 创建序列化对象,并且和文件关联在一起 CArchive
CArchive::store 把数据保存到归档文件中。允许CFile写操作。
d) 往数据流写数据(相当于往文件写数据)
ar << a << b << c
e) 断开数据流和文件的关联 CArchive::Close
f) 关闭文件 CFile::Close */
CFile file;
BOOL isOk = file.Open(TEXT("../demo.txt"),CFile::modeCreate|CFile::modeWrite); if (!isOk) {
return;
} //和CArchive管理
//CArchive对象是数据流,文件和CArchive绑定一起,
//store: 存储,写
CArchive ar(&file,CArchive::store); //和cout用法一样
int a = ;
CString str = TEXT("ABC");
TCHAR ch = 't'; //箭头代表流向
//数据流向ar, ar指向文件
ar << a << str << ch; ar.Close();//断开数据流和文件的关联
file.Close();
} //读文件
void CMainFrame::OnArchiveRead()
{
// TODO: 在此添加命令处理程序代码
CFile file;
BOOL isOk = file.Open(TEXT("../demo.txt"),CFile::modeRead); if (!isOk) {
return;
} //和CArchive管理
//CArchive对象是数据流,文件和CArchive绑定一起,
//load: 读
CArchive ar(&file,CArchive::load); //和cout用法一样
int a;
CString str;
TCHAR ch; ar >> a >> str >> ch; CString buf;
buf.Format(TEXT("%d,%s,%c"),a,str,ch);
MessageBox(buf); ar.Close();//断开数据流和文件的关联
file.Close();
}

三、文档视图案例

1)文档类自带序列化作函数 Serialize()

void CMy01_CArchiveDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: 在此添加存储代码、
//按保存按钮时调用
}
else
{
// TODO: 在此添加加载代码
//按打开按钮调用
}
}

   

// CCArchiveDoc 序列化

void CCArchiveDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring()) // //按保存,调用此处
{
// TODO: 在此添加存储代码
CString str = TEXT("Hello World");
int a = ;
ar << str << a;
}
else
{
// TODO: 在此添加加载代码 //打开文件
CString str;
int a;
ar >> str >> a;
CString buf;
buf.Format(TEXT("%s,%d"),str,a);
AfxMessageBox(buf);
}
}

画圆点

1.在doc.h中定义定义两个变量保存点的信息

// 特性
public:
CPoint m_pt[];
int m_num;

2,重写 DeleteContents() 函数,初始化数据

void CMy05_CArchiveProDoc::DeleteContents()
{
// TODO: 在此添加专用代码和/或调用基类 //AfxMessageBox(TEXT("DeleteContents")); memset(&m_pt, , sizeof(m_pt)); m_num = ; CDocument::DeleteContents();
}

3,在视图中处理鼠标左键消息,保存点的数据

// CMy05_CArchiveProView 消息处理程序

//鼠标左键
void CMy05_CArchiveProView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值 //获取文档类对象指针
CMy05_CArchiveProDoc *pDoc = GetDocument(); //不能超过200
if (pDoc->m_num > )
{
pDoc->m_num = ;
return;
} pDoc->m_pt[pDoc->m_num] = point; pDoc->m_num++; //每点完一个点,绘图
Invalidate(); //-> OnDraw() CView::OnLButtonDown(nFlags, point);
}

4,在视图中绘制点

// CMy05_CArchiveProView 绘制

void CMy05_CArchiveProView::OnDraw(CDC* pDC)
{
CMy05_CArchiveProDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return; // TODO: 在此处为本机数据添加绘制代码 for (int i = ; i < pDoc->m_num; i++)
{
pDC->Ellipse(pDoc->m_pt[i].x - , pDoc->m_pt[i].y - ,
pDoc->m_pt[i].x + , pDoc->m_pt[i].y + );
} }

5,序列化数据

// CMy05_CArchiveProDoc 序列化

void CMy05_CArchiveProDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: 在此添加存储代码 //保存数据
ar << m_num; for (int i = ; i < m_num; i++)
{
ar << m_pt[i];
} }
else
{
// TODO: 在此添加加载代码 ar >> m_num; for (int i = ; i < m_num; i++)
{
ar >> m_pt[i];
} }
}

Invalidate

  void Invalidate( BOOL bErase = TRUE );
  该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。
MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。
参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。
  它和 UpdateWindow( )区别在于:
  UpdateWindow( )的作用是使窗口立即重绘。调用Invalidate等函数后窗口不会立即重绘,这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理。调用UpdateWindow函数可使WM_PAINT被直接发送到目标窗口,从而导致窗口立即重绘。

2)学生管理系统

a)定义一个学生类Stu
b)文档类存储数据,视图类修改和显示数据
1)从尾部添加元素 CList::AddTail
2)获得此列表尾部元素的位置 CList::GetTailPosition
3)获取上一个元素 CList::GetPrev
4)获取下一个元素 CList::GetNext
5)获取首元素位置 CList::GetHeadPosition
6)获取最后一个元素位置 CList::GetTailPosition
7)获取指定位置的元素 CList::GetAt
8)移除头结点元素(并没有释放空间)CList::RemoveHead
c)视图的基类是 CFormView
d)重写文档类 DeleteContents(),做一些释放资源的操作,每次按“新建”,新建前先调用此函数

https://docs.microsoft.com/zh-cn/previous-versions/bxde0zae%28v%3dvs.110%29

新建单文档mfc工程,生成的类view选CFormView

1,student 类

class Student
{
public:
Student(int id, CString name, int age, float score);
~Student(void); int m_num;
CString m_name;
int m_age;
float m_score;
};

2,doc文档增加变量

// 特性
public:
CList<Student *> m_list;
POSITION m_pos;

3,doc文档重写DeleteContents()

// CmyviewDoc 命令

void CmyviewDoc::DeleteContents()
{
// TODO: 在此添加专用代码和/或调用基类
//每次新建前,应该清空内容 while (m_list.GetHeadPosition() != NULL)
{
//把头结点元素移除
Student *p = m_list.RemoveHead();
delete p;
} m_pos = NULL;
CDocument::DeleteContents();
}

4,视图消息处理

// CmyviewView 消息处理程序

// 提交
void CmyviewView::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
//把编辑区的内容更新到对应的变量中
UpdateData(TRUE); Student *stu = new Student(m_num,m_name,m_age,m_score); // 获取文档对象指针
CmyviewDoc *pDoc = GetDocument(); // 从尾部添加节点
pDoc->m_list.AddTail(stu);
// 获取最后一个元素节点
pDoc->m_pos = pDoc->m_list.GetTailPosition(); } // 上一个
void CmyviewView::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
Student *stu = new Student(m_num,m_name,m_age,m_score); //获取文档对象指针
CmyviewDoc *pDoc = GetDocument();
//获取上一个元素后,pDoc->m_pos会自动往上移动
pDoc->m_list.GetPrev(pDoc->m_pos); //移动到头结点的上一个无效节点
if (pDoc->m_pos == NULL)
{
//设置尾结点
pDoc->m_pos = pDoc->m_list.GetTailPosition();
} //获取当前位置的元素
Student *p = pDoc->m_list.GetAt(pDoc->m_pos); //把节点的值给变量赋值
m_num = p->m_num;
m_name = p->m_name;
m_age = p->m_age;
m_score = p->m_score; //更新到编辑区
UpdateData(FALSE); } // 下一个
void CmyviewView::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
Student *stu = new Student(m_num,m_name,m_age,m_score); //获取文档对象指针
CmyviewDoc *pDoc = GetDocument();
//获取上一个元素后,pDoc->m_pos会自动往上移动
pDoc->m_list.GetNext(pDoc->m_pos); //移动到头结点的上一个无效节点
if (pDoc->m_pos == NULL)
{
//设置尾结点
pDoc->m_pos = pDoc->m_list.GetHeadPosition();
} //获取当前位置的元素
Student *p = pDoc->m_list.GetAt(pDoc->m_pos); //把节点的值给变量赋值
m_num = p->m_num;
m_name = p->m_name;
m_age = p->m_age;
m_score = p->m_score; //更新到编辑区
UpdateData(FALSE); } // 编辑
void CmyviewView::OnBnClickedRadio1()
{
// TODO: 在此添加控件通知处理程序代码
m_buttonNext.EnableWindow(FALSE);
m_buttonPre.EnableWindow(FALSE);
} // 预览
void CmyviewView::OnBnClickedRadio2()
{
// TODO: 在此添加控件通知处理程序代码
m_buttonNext.EnableWindow(TRUE);
m_buttonPre.EnableWindow(TRUE);
}

四、数据库编程

1)准备工作

a) 安装MySQL服务器
b) MySQL odbc驱动

2)odbc层次图
a) odbc一套标准接口(内部通过sql语句操作数据库,用户就算不懂sql语句也可以借助odbc操作数据库)
b) 数据源

3)如何创建数据源(MySql只能是快照)
a)快照(Snapshot)记录集:每次操作重新查询后才更新
b)动态(Dynaset)记录集:每次操作自动更新(添加记录外)

4)应用程序框架

a) CRecordset的子类,主要是对数据库进行相应操作
1)DoFieldExchange() 自动把数据库的字段和变量相关联
2)GetDefaultConnect() 获取数据库连接信息
3)GetDefaultSQL() 获取数据库连接的表
b) CFormView的子类,显示数据库内容的视图
1)OnInitialUpdate() 主要作初始化功能

5)通过 CRecordset 类对数据库进行相应操作

a) 视图类头文件创建 CRecordset的子类对象
b) 视图类做 增删改查 操作
1)打开数据库 CRecordset::Open
2)查询记录 CRecordset::Requery
3)移动上一个记录集 CRecordset::MovePrev
4)移动下一个记录集 CRecordset::MoveNext
5)是否为最后一个记录的下一个 CRecordset::IsEOF
6)是否为第一个记录的上一个 CRecordset::IsBOF
7)移动到第一个记录 CRecordset::MoveFirst
8)移动到最后一个记录 CRecordset::MoveLast
9)添加空记录 CRecordset::AddNew
10)如果记录集可修改 CRecordset::CanUpdate
11)更新记录集 CRecordset::Update
12)删除当前记录 CRecordset::Delete
13)编辑当前记录 CRecordset::Edit
14)过滤 CRecordset::m_strFilter
15)排序 CRecordset::m_strSort(默认升序,降序加 desc)
c) 注意点
1)移动记录集,注意越界处理
2)更新记录前,先通过 CRecordset::CanUpdate 判断可更新后,才进行更新
3)删除数据后,最好移动到下一个记录集

以下针对vs2017

建立单文档MFC工程

第二步:对项目进行配置,让它可以用代码连接到数据库:

1.由于电脑和数据库有32位和64位的,所以要根据自己的电脑和安装的数据库的情况,自己选择,

点击 ‘项目’ ——》 ‘属性‘ ——》’配置管理器‘,在这里可以选择自己需要的位数;

2.点击 ‘项目’ ——》 ‘属性‘ ——》’VC++属性‘,对其包含目录,引用目录和库目录进行配置。

(1) 选中包含目录后, 右边会出现下拉箭头, 点击该箭头,再点击 ‘编辑’,把你电脑里 MySQL 安装目录中的 include文件的路径填写在编辑框里面:

 

3.对附加依赖项进行设置。

在左侧点击 ‘配置属性’——》‘链接器’——》‘输入’,然后在右边的附加依赖项中加入 “ libmysql.lib”编辑框就行了。

4.将 MySql 安装目录中 libmysql.dll和 libmysql.lib 两个文件拷贝到当前项目的主目录下,以及主目录下与项目名同名的文件夹下。

写到这数据库基本已经可以连上了

下面开始写代码,但在这之前要在数据库中新建一个数据库(test)

3.数据上传在‘插入’按钮的消息处理函数中实现,代码如下:

//因为数据库是通过网络连接的,必须包含网络相关头文件
#include "winsock.h"
//这个没什么好说的,mysql头文件自然要包含
#include "mysql.h"
void Cmysql_testDlg::OnBnClickedInsertButton()
{
// TODO: 在此添加控件通知处理程序代码
MYSQL m_sqlCon;
//初始化数据库对象
mysql_init(&m_sqlCon); //localhost:服务器地址,可以直接填入IP;root:账号;
//123:密码;test:数据库名;3306:网络端口
if (!mysql_real_connect(&m_sqlCon, "localhost", "root",
"", "test", , NULL, ))
{
AfxMessageBox(_T("数据库连接失败!"));
return;
}
else//连接成功则继续访问数据库,之后的相关操作代码基本是放在这里面的
{
AfxMessageBox(_T("数据库连接成功!")); UpdateData(true);
//设置数据库字符格式,解决中文乱码问题
mysql_query(&m_sqlCon, "set names 'gb2312'");
char* num = (char*)m_num.GetBuffer();
char* name = (char*)m_name.GetBuffer();
char* age = (char*)m_age.GetBuffer(); char insert[];
sprintf_s(insert, "insert into student(num, name, age) values (\'%s\', \'%s\', \'%s\')",
num, name, age); // 执行 sql 语句。
// mysql_query() 的返回值份很多情形, 进行判断使要注意。
if (mysql_query(&m_sqlCon, insert) == )
{
AfxMessageBox(_T("插入数据成功!"));
}
else {
AfxMessageBox(_T("插入数据失败!"));
}
}
UpdateData(false);
mysql_close(&m_sqlCon);//关闭Mysql连接 }

这样代码已经写好了,但是还要修改字符集

点击 ‘项目’ ——》 ‘属性‘ ——》‘常规’,在右面有个字符集,把它改成 ‘使用多字节字符集’

这样在向数据库中写入数据室就不会报错了。

vs2015

(九)文档和视图,Invalidate,数据库编程的更多相关文章

  1. VS2010/MFC编程入门之三十九(文档、视图和框架:概述)

    前面几节讲了菜单.工具栏和状态栏的使用,鸡啄米本节开始将为大家讲解文档.视图和框架的知识. 文档.视图和框架简介 在VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)创建的单文档工 ...

  2. VS2010/MFC编程入门之四十一(文档、视图和框架:分割窗口)

    上一节中鸡啄米讲了文档.视图和框架结构中各对象之间的关系,本节主要讲讲在MFC中如何分割窗口. 分割窗口概述       分割窗口,顾名思义,就是将一个窗口分割成多个窗格,在每个窗格中都包含有视图,或 ...

  3. VS2010/MFC编程入门之四十(文档、视图和框架:各对象之间的关系)

    前面一节中鸡啄米进行了文档.视图和框架的概述,本节主要讲解文档.视图.框架结构中各对象之间的关系. 各个对象之间的关系 文档.视图.框架结构中涉及到的对象主要有:应用程序对象.文档模板对象.文档对象. ...

  4. 理解MFC 文档、视图、框架[转]

    理解文档/视图框架                                      出处.雷神 了解文档和视图的相互作用关系是编写MFC程序的基本功.但是MFC的应用程序框架把文档和视图之间 ...

  5. VS2010-MFC(文档、视图和框架:分割窗口)

    转自:http://www.jizhuomi.com/software/226.html 上一节讲了文档.视图和框架结构中各对象之间的关系,本节主要讲讲在MFC中如何分割窗口. 分割窗口概述      ...

  6. VS2010-MFC(文档、视图和框架:概述)

    转自:http://www.jizhuomi.com/software/221.html 前面几节讲了菜单.工具栏和状态栏的使用,本节开始将为大家讲解文档.视图和框架的知识. 文档.视图和框架简介 在 ...

  7. MFC文档、视图和框架

    文档.视图.框架 文档/视图结构是MFC提供的一种不错的设计,它将数据的处理和显示分开来,这样更便于我们对程序的维护和扩展. 文档        文档对象用于管理和维护数据,包括保存数据.取出数据以及 ...

  8. VS2010-MFC(文档、视图和框架:各对象之间的关系)

    转自:http://www.jizhuomi.com/software/223.html 前面一节进行了文档.视图和框架的概述,本节主要讲解文档.视图.框架结构中各对象之间的关系. 各个对象之间的关系 ...

  9. 阿里P7整理“硬核”面试文档:Java基础+数据库+算法+框架技术等

    现在的程序员越来越多,大部分的程序员都想着自己能够进入大厂工作,但每个人的能力都是有差距的,所以并不是人人都能跨进BATJ.即使如此,但身在职场的我们一刻也不能懈怠,既然对BATJ好奇,那么就要朝这个 ...

随机推荐

  1. 剑指offer26:将二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

    1 题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 2 思路和方法 在二叉搜索树中,每个结点都有两个分别指向其左.右子树的 ...

  2. Python 闭包、迭代器、生成器、装饰器

    Python 闭包.迭代器.生成器.装饰器 一.闭包 闭包:闭包就是内层函数对外层函数局部变量的引用. def func(): a = "哈哈" def func2(): prin ...

  3. 以太坊再爆高危漏洞!黑客增发ATN 1100万枚token事件始末

    事情发生在5月中旬,ATN技术人员发现Token合约由于存在漏洞受到攻击.不过ATN基金会随后透露,将销毁1100万个ATN,并恢复ATN总量,同时将在主链上线映射时对黑客地址内的资产予以剔除,确保原 ...

  4. MyBatis MyBatis Generator入门

    一.MGB功能简介 MyBatis Generator是一个代码生成工具. MBG是如何运行的呢?它会检查所连接到的数据库的一个或者多个table,然后生成可用来访问这些table的构建(Java代码 ...

  5. .Net C# RSA签名和验签重写

    namespace com._80community.unittest.CUP { /// <summary> /// CUP Client /// </summary> pu ...

  6. C语言两个特别大的整数类型相加超出范围使用两个技巧

    技巧1:用long (%ld)或者long long(%lld)类型存取 技巧2:当两个同号的数字相加,放到等号的另一边,变成减号 问题: 给定区间[-2的31次方, 2的31次方]内的3个整数A.B ...

  7. MyEclipse的Server标签出现:Could not create the view: An unexpected exception was thrown

    删除工作空间下的.metadata\.plugins\org.eclipse.core.runtime\.settings\com.genuitec.eclipse.ast.deploy.core.p ...

  8. caffe训练时报错

    转自:https://www.cnblogs.com/haiyang21/p/7614669.html F0717 :: math_functions.cu:] Check failed: statu ...

  9. 安卓App自动升级

    procedure _InstallApk(Apk: string); var LFile: JFile; LIntent: JIntent; begin LFile := TJFile.JavaCl ...

  10. gulp 实现sass自动化 ,监听同步

    实现功能 监听scss文件 sass自动化 准备条件 1 .安装gulp npm init   ---->一直enter,会在当前目录下生成一个package.json文件,记录安装的依赖模块 ...