一、文档视图结构

文档类(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. ecshop二次开发笔记

    1. robots.txt 爬虫协议 网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取. 2. 入口文件 index.php 3. 目录结构分析 admin 后台 api 接口 ...

  2. python学习-7 条件语句 while循环 + 练习题

    1.死循环 while 1 == 1: print('ok') 结果是一直循环 2.循环 count = 0 while count < 10: print(count) count = cou ...

  3. Linux (x86) Exploit 开发系列教程之四(使用return-to-libc绕过NX bit)

    (1)原理: “NX Bit”的漏洞缓解:使某些内存区域不可执行,并使可执行区域不可写.示例:使数据,堆栈和堆段不可执行,而代码段不可写. 在NX bit打开的情况下,基于堆栈的缓冲区溢出的经典方法将 ...

  4. spark异常篇-关闭程序

    在运行 spark 程序时,出于某种原因,我想停止运行,狂按 ctrl+c 不一定起作用 以下两种情况是不好关闭的 1. cluster 运行模式 2. SparkStreaming 程序 本文旨在收 ...

  5. 测试工作小工具~总结&下载连接

    1.Gif录制小工具(动图提单 ≖ᴗ≖) 地址:https://licecap.en.softonic.com/download

  6. Lua模除运算的大坑

    问题 对负数进行模除运算遇到的坑,Lua的%运算与C++的%有差异 实践 结论 Lua%运算的基本公式 a % b = a - ( ( a // b ) * b ) 1.在C,C++中 %运算符的取整 ...

  7. 由[].slice.call()引发的思考

    由[].slice.call()引发的思考   经常看到大家用[].slice.call()或者Array.prototype.slice.call():  我一直是一知半解的,今天算是基本弄清楚了, ...

  8. MySQL - 性能优化 & MySQL常见SQL错误用法(转载)

    1. LIMIT 语句 分页查询是最常用的场景之一,但也通常也是最容易出问题的地方.比如: , ; 一般DBA想到的办法是在type, name, create_time字段上加组合索引.这样条件排序 ...

  9. 1-MySQL DBA笔记-理解MySQL

    第一部分 入门篇 本篇首先介绍MySQL的应用领域.基础架构和版本,然后介绍MySQL的基础知识,如查询的执行过程.权限机制.连接.存储引擎,最后阐述一些基础概念. 第1章 理解MySQL 本章将介绍 ...

  10. VBA精彩代码分享-3

    在开发VBA程序中,我们可能会需要用代码处理VBA工程,包括启用VBA工程访问,启用所有宏,动态插入代码,动态删除代码,动态添加引用和自动创建模块等等,本次的分享内容便以这些为主. 启用VBA工程访问 ...