770 likes | 978 Views
C++ 语言程序设计 第十六章. 山东师范大学管理学院 刘希玉 Email: sdxyliu@beelink.com xyliu@sdnu.edu.cn. 课程目录. 第 1 章 概论 第 2 章 数据类型和表达式 第 3 章 指针和引用 第 4 章 条件、循环及编译预处理 第 5 章 函数 第 6 章 类和对象 第 7 章 继承和派生 第 8 章 多态性和虚函数 第 9 章 字符串和文件 I/O 第 10 章 MFC 应用程序概述 第 11 章 GUI 设计及菜单
E N D
C++语言程序设计第十六章 山东师范大学管理学院刘希玉Email: sdxyliu@beelink.comxyliu@sdnu.edu.cn
课程目录 • 第1章 概论 • 第2章 数据类型和表达式 • 第3章 指针和引用 • 第4章 条件、循环及编译预处理 • 第5章 函数 • 第6章 类和对象 • 第7章 继承和派生 • 第8章 多态性和虚函数 • 第9章 字符串和文件I/O • 第10章 MFC应用程序概述 • 第11章 GUI设计及菜单 • 第12章 创建和使用对话框 • 第13章 应用程序的组成元素 • 第14章 简单的图形和文本输出 • 第15章 Windows 标准控件 • 第16章 Visual C++数据库编程 • 第17章 ACIS的简介与环境配置 • 第18章 ACIS的实例代码 • 第19章 程序调试
第十六章 Visual C++数据库编程 • 16.1 Visual C++开发数据库的特点 • 16.2 MFC ODBC数据库访问技术 • 16.3 使用DAO 技术访问数据库 • 16.4 OLE DB 和ADO技术概述
16.1 Visual C++开发数据库的特点 • Visual C++ 提供了多种的数据库访问技术:ODBC API、MFC ODBC、DAO、OLE DB、 ADO等。这些技术各有自己的特点,它们提供了简单、灵活、访问速度快、可扩展性 强的开发技术,这些正是Visual C++开发数据库程序的优势所在,归纳起来主要有以下 几点: • 简单性 Visual C++ 提供了MFC类库、ATL模板类以及AppWizard、ClassWizard等一系列Wizard工具,掌握它们会达到事半功倍的效果;而且MFC ODBC和ADO数据库接口已经将一些底层的操作都封装在类中,用户可以方便的使用这些接口而无需编写操作数据库的底层代码。 • 可扩展性 Visual C++提供的OLE和ActiveX技术可以让开发者利用Visual C++中提供的各种组件、控件以及第三方开发者提供的组件来创建自己的程序,从而实现应用程序的组件化,而组建化的应用程序则会具有良好的可扩展性。 • 访问速度快 Visual C++为了解决ODBC开发的数据库应用程序访问数据库速度慢的问题,提供了新的访问技术——OLE DB和ADO,它们都是基于COM口的技术,使用此技术可以直接对数据库的驱动程序进行访问,这大大提高了对数据库的访问速度。 • 数据源友好 传统的ODBC技术只能访问关系型数据库,而在Visual C++中通过OLE DB技术不但可以访问关系型数据库,还可以访问非关系型数据库。
Visual C++ 6.0开发数据库的相关技术 • Visual C++提供了许多种访问数据库的技术,如下所示: • ODBC (Open DataBase Connectity) • MFC ODBC (Microsoft Foundation Classes ODBC) • DAO (Data Access Object) • OLE DB (Object Link and Embedding DataBase) • ADO (ActiveX Data Object)
DBC 和MFC ODBC • ODBC是为客户应用程序访问关系数据库是提供的一个标准接口,对不同的数据库,ODBC提供了一套统一的API,使得应用程序可以应用所提供的API,访问任何提供了ODBC驱动程序的数据库。而且,由于ODBC已经成为一种标准,所以现在几乎所有的关系数据库都提供了ODBC的驱动程序,从而使得ODBC应用更加广泛。 • 由于ODBC是一种底层的访问技术,因此,ODBC API可以使客户应用程序能够从底层设置和控制数据库,完成一些高层数据库技术无法完成的功能。但是ODBC PAI代码编制相对来说比较复杂,而MFC ODBC 是Visual C++对ODBC API 封装得到的,因此可以简化程序设计,但缺点也是不言而喻的,那就是无法对数据源进行底层操作。
DAO • DAO提供了一种通过程序代码创建和操作数据库的机制。多个DAO构成一个体系结构,在这个结构中各个DAO对象是协同工作的。MFC DAO是微软公司提供的用于访问Microsoft Jet数据库文件(.mdb)的强有力的数据库开发工具,它通过DAO的封装,向程序员提供了DAO丰富的操作数据库手段。
OLE DB 和ADO • OLE DB是Visual C++开发数据库应用中提供的基于COM接口的新技术,因此OLE DB对所有的文件系统(关系与非关系数据库)都提供了统一的接口。这些特性使得OLE DB技术比传统的数据库访问技术更加优越。它属于数据库访问技术中的底层借口,在VC中提供了ATL模板来设计OLE DB数据应用程序和数据提供程序。 • 而DAO技术则是基于OLE DB的访问借口,对OLE DB的接口作了封装,定义了ADO对象,使得程序开发得到简化,它属于数据库访问的高层接口。
第十六章 Visual C++数据库编程 • 16.1 Visual C++开发数据库的特点 • 16.2 MFC ODBC数据库访问技术 • 16.3 使用DAO 技术访问数据库 • 16.4 OLE DB 和ADO技术概述
16.2 MFC ODBC数据库访问技术 • ODBC是一种使用SQL的程序设计接口。使用ODBC让程序的编写避免了与数据库相连的复杂性。这项技术目前已经得到了大多数DBMS厂商的广泛支持。Microsoft Developoer Studio为大多数标准的数据库格式提供了32位的ODBC驱动器,比如SQL Server、Access、Paradox、ForPro、Excel、Oracle等。如果用户需要用其他的数据库格式,用户需要相应的ODBC驱动以及DBMS。 • MFC的ODBC类对较复杂的ODBC API进行了封装,提供了简化的调用接口,从而大大方便了数据库应用程序的开发。程序员不必了解ODBC API和SQL的具体细节,利用ODBC类就可以完成对数据库的大部分操作。MFC 的ODBC类主要包括如下5类: • CDatabase类:主要功能是建立与数据源地联接。 • CRecordset类:代表从数据源选择的一组记录(记录集)。 • CRecordView类:提供了一个表单视图与某个记录集直接相连,利用对话框数据交换机制(DDX)在记录集与表单视图的空间之间传输数据。 • CFieldExchange类:支持记录字段数据交换(DFX),即记录集字段数据成员于相应的的数据库的表的字段之间的数据交换。 • CDBException类:代表ODBC类产生的异常。
使用MFC ODBC编程建立应用程序 • 相对于使用ODBC API,使用MFC ODBC访问数据库简单得多,其步骤如下: • 首先创建数据库并在系统中设置好; • 使用CDatabase打开数据源的连接,如果利用AppWizard生成一个ODBC数据库应用程序,则会自动完成操作。 • 使用ClassWizard想到加入由CRecordset类派生的用户记录集,完成对数据库表的绑定。 • 创建记录积累对象,如果利用 AppWizard生成一个ODBC数据库应用程序,则会自动在文档类中创建。 • 使用记录集对象对数据库进行遍历、增加、删除、和修改等操作。 • 使用CDatabase类的ExecuteSQL函数直接执行SQL命令。 • 使用CDatabase类的BeginTrans、CommitTrans和Rollback函数进行事务处理。 • 使用CDatabase类的Close函数关闭数据源连接。
建立数据库 • 这里我们采用Access各式的数据库,数据库创建过程如下: • * 创建一个名为demo01的数据库; • * 建立一个新的数据表,表名记为puser,用于存储用户信息。这里我们建立 一个用户登录系统的界面,只要存放用户的ID,用户名、密码、以及权限即可。 将这些作为表中的字段建立,并存储相应的数据。如图16.2.1所示。
设置数据源 • 创建好数据库后我们还要进行配置,以便程序通过ODBC数据源来访问刚刚创建的数据库。不同的Windows操作系统中数据源的配置过程不尽相同,但差别不是很大,本例以Windows XP系统为例。具体操作如下: • (1)选择开始菜单“控制面板——管理工具——数据源(ODBC)”,弹出“ODBC数据源管理器”对话框,选择“系统DSN”选项卡,单击[添加]按钮,如图16.2.2所示。
在弹出的“创建新数据源”对话框中,选择“Microsoft Access Driver (*.mdb)”,如图16.2.3所示,单击[完成]按钮。
在弹出的“ODBC Microsoft Access 安装”对话框中,配置数据源属性。如图16.2.4所示,依次配置数据源名为“demo01”,说明为“第一个Demo的数据库”,当然此处可以省略,我们只是为了更清楚地明白数据源的意义而添加此项的。单击[选择]按钮。
在弹出的“选择数据库”对话框中选择我们要用作数据库的Access文件“demo01.mdb”,找到“demo01.mdb”的路径,选中文件,单击[确定]按钮,如图16.2.5。
此时退回到图16.2.4所示的“ODBC Microsoft Access 安装”对话框,可以看到其中的“数据库”标签后面增加了一行“E:\zdc\demo01\demo01.mdb”,这就是本例数据源所对应的数据库,单击[确定]按钮。 • (6) 此时退回到图16.2.2所示的“ODBC数据源管理器”对话框,可以看到已经存在了名为“demo01 Microsoft Access Driver (*.mdb)”的数据源。单击[确定]按钮,结束数据源的配置过程。 • 至此数据源的配置过程完成,后面需要进行Visual C++的程序编写了。
制作用户登录模块 • (1)打开“Microsoft Visual C++ 6.0”,选择“File——New”命令菜单,弹出“New”窗口,选择“Projects”选项卡后在列表中选择“MFC AppWizard (exe)”,确定工程名称为“Demo01”,并选择工程存放路径。 • (2)在如图16.2.6所示的“MFC 应用程序向导步骤1”对话框中,选中“基本对话框”项,我们要创建的是一个用户登录界面,建立一个登录对话框即可。其他保持默认值,单击[下一步]按钮。
(3) 在“MFC 应用程序向导步骤2”对话框中,保持各选项的默认值,单击[Next]按钮。 • (4)在如图16.2.7所示的“MFC 应用程序向导步骤3”对话框中,选择第三项“您希望使用MFC库吗?”为“作为静态的DLL”。其他各项保持默认值,然后单击[下一步]按钮。
在如图16.2.8所示的“MFC 应用程序向导步骤4”对话框中,保持各项默认值,然后单击[完成]按钮。
(6)在最后弹出的对话框中,单击[确定]按钮,完成工程的创建。(6)在最后弹出的对话框中,单击[确定]按钮,完成工程的创建。 • 至此,基于对话框的工程创建出来了,整个工程包含一个程序“Demo01”,整个程序包含一个默认的对话框。 • 编辑对话框资源 • 将主编辑区切换到要编辑的对话框上,如图16.2.9所示,
添加变量 • 要想让对话框类中的变量接受对话框上控件的输入或向对话框输出,必须将控件与相应的变量关联起来,以简化“控件—变量”之间频繁的数据交换,在我们要实现的用户登录界面中要为用户名和密码的输入作控件变量关联。 • 为输入用户名的编辑框控件进行变量关联。选择“查看—建立类向导”菜单命令,在弹出的“MFC ClassWizard”对话框中,切换到“Member Variables”选项卡,如图16.2.10所示,然后在Class name下拉框中选择“CDemo01Dlg”项,并且在Control ID单选框中选择“ID_USER_NAME”,最后单击[Add Variables]按钮。
进行变量定义。如图16.2.11,在弹出的“Add Member Variable”对话框中,依次在Member variable name 框中输入“m_username”,在Category下拉框中选择“Value”项,在“Variable type”下拉框中选择“CString”项,最后单击[OK]按钮完成设置。
重复以上步骤,为输入密码的编辑框控件设置一个变量m_userpwd。重复以上步骤,为输入密码的编辑框控件设置一个变量m_userpwd。 • 在这个例子中只要为以上两个控件连接变量就足够了,完成所有的变量配置后在“MFC ClassWizard”对话框中单击[OK]按钮保存刚才的设置,这样才可以起作用。
连接数据库 • 我们需要创建一个CRecordSet类的派生类CUserRecordset类来操作数据库“Demo01.mdb”的表“puser”。 • 创建CUserRecordset类。将WorkSpace切换到“ClassView”选项卡,如图16.2.12,在“Domo01Classes”位置单击鼠标右键,然后选中“New Class”菜单命令。
从CRecordSet派生新类“CUserRecordset”。在弹出的如图16.2.13所示的对话框中,依次在Base class下拉框中选择“CRecoedSet”项,在Name下拉框中选择“CUserRecordset”,然后单击[确定]按钮。
选择数据源。在弹出的Database Option对话框中,在Datasource单选框中选择ODBC数据源类型,然后在ODBC数据源的下拉框中选中“demo01”,其他选项可以保持默认值,如图16.2.14,最后单击[OK]按钮
在弹出的对话框“Select Database Tables”中选择数据表,如图16.2.15,选中我们前面创建的表“puser”,单击[OK]按钮,这时我们可以看到在图16.2.12所示的位置自动增加了一个“CUserRecordset”
到现在为止我们已经创建完了连到数据库的类“CUserRecordset”。这时在工作区的“ClassView”窗口中我们可以看到在新添加的派生类“CUserRecordset”中已经自动定义了4个变量,如图16.2.16,这4个变量正好与我们创建的表“puser”中的字段同名,并且类型也是一致的。这是MFC自动添加的变量,以绑定我们刚才选中的表中的字段。需要说明的是,如果表中字段的名是中文,则MFC会自动创建m_column1、m_column2等这样的变量名来对应表中的字段。到现在为止我们已经创建完了连到数据库的类“CUserRecordset”。这时在工作区的“ClassView”窗口中我们可以看到在新添加的派生类“CUserRecordset”中已经自动定义了4个变量,如图16.2.16,这4个变量正好与我们创建的表“puser”中的字段同名,并且类型也是一致的。这是MFC自动添加的变量,以绑定我们刚才选中的表中的字段。需要说明的是,如果表中字段的名是中文,则MFC会自动创建m_column1、m_column2等这样的变量名来对应表中的字段。
增加“确定”按钮的消息响应代码 • 在我们创建的用户登录界面中,要求点击“确定”按钮时,程序能进行密码验证的操作,这就要求为[确定]按钮增加一个响应“鼠标点击”的函数,实质就是重载[确定]按钮的“OnOK”函数。 • 选中“View—ClassWizard”菜单命令,在弹出的“MFC ClassWizard”对话框中,选中“Message Map”选项卡。 • 增加消息响应函数。在弹出的如图16.2.17所示的对话框中,依次在Class Name下拉框中选择CDemo01Dlg项,在Object IDs单选框中选择IDOK项,在Message单选框中选择BN_CLICKED项,然后单击[Add Function]按钮来为此消息增加消息响应寒暑,此时会弹出一个确认框,保持其中的默认值并确认。操作完后我们可以看到在图中新增加了一行“OnOK ON:IDOK:ON_CLICKED”,这就是新增加的消息响应函数。 • [取消]按钮的响应函数与此类似,只不过它是重载了“OnClose”函数。保存刚才的设置,消息响应函数就添加完成了。此时切换到“WorkSpace”的“ClassView”选项卡,在“CDemo01Dlg”类中,可以看到其中增加了一个“OnOK”函数。
编写“密码验证”代码 • 以上我们只是为[确定]按钮添加了一个响应鼠标单击消息的函数,如果我们要求在单击此按钮时能够对输入的数据进行密码验证,则必须在此响应函数中增加用于密码验证的代码,在编辑区打开“OnOK”的函数定义,在此函数中编辑添加代码如下:
void CDemo01Dlg::OnOK() { // TODO: Add extra validation here UpdateData(TRUE); CUserRecordsetm_user; Try { if(m_user.IsOpen()); m_user.Close(); m_user.m_strFilter.Format("username='%s' and userpwd='%s'",m_Uname,m_Upwd); m_user.Open(CRecordset::snapshot,NULL,CRecordset::none); if(m_user.IsEOF()) {m_user.Close(); AfxMessageBox("密码错误,请重试!"); return; } else {m_user.Close(); AfxMessageBox("登录成功!!"); } } catch(CDBException* e) { e->ReportError(); return; } CDialog::OnOK(); }
下面解释一下其中用到的部分函数和方法: • UpdateData(TRUE):将表单中控件的输入内容更新到所关联的变量上,也就是让位两个编辑框控件的变量m_username和m_userpwd获得输入值。 • CUserRecordsetm_user:生成一个CUserRecordset类的实例m_user,用以操作数据库中定义的表“puser”。 • Try{…}Catch{…}:用以捕获意外,用CDBException类的实例来捕获数据库中可能出现的错误,e->ReportError();表明将错误报告到界面上。 • if(m_user.IsOpen()); m_user.Close();判断puser记录集是否打开,如果打开的话则关闭,以保证后边的操作能正确执行。 • m_user.m_strFilter.Format("username='%s'anduserpwd='%s'",m_Uname,m_Upwd):定义查询语言,其对应规则为:“username= m_Uname and userpwd= m_Upwd”。 • m_user.Open(CRecordset::snapshot,NULL,CRecordset::none):执行查询操作。 • if(m_user.IsEOF()) {…} else {…}:判断是否已经查询到表的末尾,如果是的话表明没有符合的用户,用户名或密码错误,否则提示登录成功。 • m_user.Close():操作完后要及时关闭数据库,保证其他操作的正确执行。 • AfxMessageBox("密码错误,请重试!"):利用标准信息框,输出警告信息。
编译 • 选择菜单“Build—Rebuild All”即可编译程序。我们看到在调试区出现了大堆错误,因为其中忘了两点重要的内容: • 选择WorkSpace的FileView选项卡,在编辑区打开文件“Demo01 files\Header Files\StaAfx.h”,在其中加入下面的内容: • #include<afxdb.h> • 这是与CRecordSet调用相关的头文件声明。 • 打开文件“Demo01 files\Source Files\Demo01Dlg.cpp”,在其中加入下面的内容: • #include "UserRecordset.h" • 这是与CUserRecordset调用相关的头文件声明。 • 因为在程序中调用了CRecordSet类,又在CDemo01Dlg中调用了CUserRecordset类,因此必须要作相应的头文件声明。 • 重新编译,可以看到显示没有错误,编译成功。 • 单击图中的红色感叹号来运行程序。
第十六章 Visual C++数据库编程 • 16.1 Visual C++开发数据库的特点 • 16.2 MFC ODBC数据库访问技术 • 16.3 使用DAO 技术访问数据库 • 16.4 OLE DB 和ADO技术概述
16.3 使用DAO 技术访问数据库 • DAO(Database Access Object,数据访问对象)使用Microsoft Jet数据库引擎来访问数据库。Visual C++6.0提供了对DAO的封装,MFC DAO类封装了DAO的大部分功能,从而Visual C++6.0程序就可以使用MFC DAO类方便的访问Microsoft Jet数据库。 • Microsoft Jet 是一种数据管理组件,许多数据工具(如Access)都是通过它实现其功能的,同时,通过Jet引擎可以访问数据库中的数据和数据库结构定义。DAO通过Microsoft Jet数据引擎提供了一套对象,包括:数据库对象(Database)、表定义(TableDef)、查询定义对象(QueryDef)和记录集对象(Recordset)等。MFC DAO封装了DAO的功能,说到底是通过Microsoft Jet数据引擎来访问系统和用户数据库中的数据的。 • 一般来说,基于DAO的MFC类比基于ODBC的MFC类处理功能更强。因为基于DAO的类可以通过ODBC驱动,也可以通过自己的数据库引擎(Jet)存取数据。
DAO支持以下4个数据库选项 • 打开访问数据库(mdb文件)。Mdb文件是一个自饱含的数据库,它包括查询定义、安全信息、索引、关系,当然还有实际的数据表。用户只需指定mdb文件的路径。 • 直接打开ODBC数据源。这里有一个很重要的限制,不能打开以Jet引擎作为驱动程序的ODBC数据源,只可以使用具有自己的ODBC驱动程序的DLL的数据源。 • 用Jet引擎打开ISAM型(索引顺序访问方法)数据源。 即使已经设置了ODBC数据源,要用Jet引擎访问这些文件类型中的一种,也必须以ISAM型数据源方式打开文件,而非ODBC数据源方式。 • 给Access数据库附加外部表。这实际上是用DAO访问ODBC数据源的首选方法。首先要用Access把ODBC表添加到一个mdb文件上,然后依照第一选项中介绍的方法用DAO打开这个mdb文件就可以了。也可以用Access把ISAM文件附加到一个mdb文件上。
需要指出的是,由于Visual C++6.0不支持Access97以后版本生成的mdb数据库,所以需要将Access2000等生成的数据库更改格式,才可以被Visual C++6.0所用。下面介绍如何改变Access数据库到老版本: • 首先用Access2000打开需要转换的数据库。 • 单击菜单上面的[工具]—>[数据库实用工具]—>[转换数据库]—>[到早期Access数据库版本],如图16.3.1所示
与ODBC的比较 • DAO与ODBC类有许多相似之处,主要有以下几点: • 两者都支持对各种ODBC数据源的访问。虽然两者使用的数据引擎不同,但都可以满足用户编写独立与DBMS应用程序的要求。 • DAO提供了与ODBC功能相似的MFC类。例如DAO的 Cdatabase类对应 ODBC的 Cdatabase类, CdaoRecordset类对应 ODBC的 Cracordset类等等。这些对应的类功能相似,他们大部分的成员函数都是相同的。 • AppWizard 和ClassWizard对使用DAO和ODBC对象的应用程序提供了类似的支持。
一般来说,基于DAO的MFC类比基于ODBC的MFC类处理功能更强。因为基于DAO的类可以通过ODBC驱动,也可以通过自己的数据库引擎(Jet)存取数据。但是,ODBC 和DAO访问数据库的机制是完全不同的。 • ODBC的工作依赖于数据库制造商提供的驱动程序,使用ODBC API时,Windows 的ODBC管理程序把对数据库访问的请求传递给正确的驱动程序,驱动程序再使用SQL语句指示DBMS完成数据库访问工作。 • 类CdaoDatabase提供了一个和MFC ODBC 类Cdatabse类似的接口,但它们之间有区别,表现在Cdatabase是通过ODBC和ODBC驱动程序存取数据的,而CDaoDatabase则是通过数据存取对象存取数据的。 • DAO则不需要中间环节,它直接利用Microsoft Jet 数据库引擎提供的数据库访问对象集进行工作。因此缺少了中间环节,直接访问数据库,所以速度比ODBC快。
使用DAO 技术访问数据库 • 本例是实现一个特殊的浏览器,数据库中存有被禁止的网址,访问时,如果是被禁止的网址则禁止访问,如果不是则可以浏览该网址并且可以记录访问网址的情况;并且可以往数据库中添加删除禁止访问的网址。本节介绍的例子不是单个的模块,而是一个比较简单但完整的系统,而且它涉及到了多个表的操作,包括对数据库的读取和写入。
设计数据库 • 创建一个Access数据库,命名为Demo02,创建两个表,pDomain和pLog分别用来存储被禁止的网址和访问网址的记录。 • 如图16.3.2 16.3.3所示:
制作浏览器 • 创建VC工程 • 首先要创建一个基于HtmlView的工程,其步骤如下: • 选择创建一个新的“MFC AppWizard(exe)”工程,此处我们命名为Demo02。 • 在“MFC 应用程序向导步骤1”对话框中,设置程序类型为第一项“单文档”。 • 在“MFC 应用程序向导步骤2”到“MFC 应用程序向导步骤4”对话框中选择默认值。 • 在“MFC 应用程序向导步骤5”中,将第三问“您希望使用MFC库吗?”选中“作为静态的DLL”如图16.3.4所示:
在“MFC 应用程序向导步骤6”对话框中,选择“基类”为“HtmlView”类,如图,单击[完成]按钮,完成工程创建。
实现“网页浏览”功能 • 去除工具条和状态栏等。切换到“WorkSpace | ClassView | Demo02 Classes | CmainFrame | OnCreat(LPCREATSTRUCT lpCreateStruct)”,找到下面几行注释掉,如图16.3.6所示: