目 录
摘 要……………………………………………………………………………2
前 言……………………………………………………………………………2
1文档管理系统综述…………………………………………………………3
2文档管理系统应用设计……………………………………………………4
2.1 可行性分析…………………………………………………………………4
2.2开发工具说明………………………………………………………………5
2.2.1数据库简介……………………………………………………………5
2.2.2 Access功能特点……………………………………………………8
2.2.3几种VC++数据库开发技术的比较…………………………………12
3 齐心文档管理系统的设计和实现………………………………………16
3.1齐心数据库访问的实现…………………………………………………16
3.1.1 齐心数据库访问技术……………………………………………16
3.1.2.数据访问编程……………………………………………………17
3.2 系统实现…………………………………………………………………20
3.2.1 系统功能分析……………………………………………………20
3..2.2 系统功能模块设计………………………………………………28
3.3 齐心系统文件浏览的实现………………………………………………28
附录………………………………………………………………………………33
参考文献………………………………………………………………………47
基于VC++的文档管理系统开发
——齐心管理系统开发
摘 要:本文主要讲解一种实用软件的开发过程—基于VC++的文档管理系统。首先对当前几种常用的文档管理软件作了介绍,然后对文档管理系统的功能模块分析,最后对界面制作,建立数据库以及连接数据库及相关知识,以及控件的制作方法进行了说明。
关键词:VC++ 、Access、DAO、 控件、数据库
Documents Managent Based On VC++
--Qi Xin Managent System-Making
Abstract:This paper is about a useful software develop process--File Management System Base on VC++ .first there is a introduce about several,File management software currently in common use ,then there is a analysis on Function Module of the file management system,last told the user interface design,create Database and Database connect and so on,some about the method of the controlware facture.
KeyWord: VC++、Access、ADO、controlware、database
前 言
随着计算机技术的飞速发展,计算机在企业管理中应用的普及利用计算机实现文档管理势在自必行。办公自动化是企事业单位在信息化建设基本阶段的典型需求,目的是为了规范企事业单位的日常工作流程和员工的日常行为。文档管理是管理事业中一项很重要的管理工作。它以知识管理为核心,以沟通、协调、控制为宗旨,将现代化办公管理思想和计算机、网络、通讯等信息工具高度集成,。它的实施能够提高工作效率,加强工作的沟通与协作,实现文档的高效管理。使用Access作为后台数据库,前台采用Visual C++语言作为开发语言。是一个软件开发的典型应用。课题涉及数据库的基础知识、Dao访问技术以及通用界面的设计等关键技术,具有一定的难度。通过本课题可以熟悉Visual C++语言的使用及数据库的知识,对将来的工作有着极其重要的意义。
本系统是为了解决日常办公中大量文档资料的搜集、保存等办公问题而设计的软件系统。在当今世界个人电脑普及的时刻,人们已经习惯于用电脑办公,结果产生大量的电子文件,这些文件有宝贵的历史价值,但我们如果将更多的时间花费在寻找这些文件上,既费时又费力。本产品正式基于用户的这种需求,设计出了方便用户查找、管理个人文档、资料的知识管理软件,使它成为您得力的文档管理助手。
文档管理系统开发的主要工具是Visual C++ 和Access 2000,运作平台是Windows 98以上的操作系统。开发本软件的主要目的是为了实现对文档供应整个流程的管理。
1文档管理系统综述
目前市场上用的比较普遍的文档管理系统主要有瑞软文档管理系统、PDF文档管理系统、百灵鸟文档管理系统等等。我们在这里结合 ISO9000 标准文档管理系统对这些文档管理系统的特性进行介绍。
所谓的文档管理系统,通俗而言就是一种用于PC文档管理的软件。系统应该具备文档编制辅助系统、文档权限管理、文档变更管理、文档审签管理、借阅与回收、技术类文档的发放回收等功能。比如瑞软文档管理系统就是一套应用于企事业单位的办公自动化管理软件,它以知识管理为核心,以沟通、协调、控制为宗旨,将现代化办公管理思想和计算机、网络、通讯等信息工具高度集成而开发的一款OA软件系统。它的实施能够提高工作效率,加强工作的沟通与协作,实现企事业单位的高效管理。还具备公文收发、电子通知、电子公告、电子信函、网络会议、常用工具等功能。
PDF文档管理系统应用由美国Adobe公司开发的eBook移动文件格式-PDF(Portable Document Format)为归档格式 ,全面支持Microsoft Office的DOC、RTF、XLS、HTML、TXT等电子文件到PDF文件的自动转换 ,全自动文档属性和全文信息自动入库。个人系统里大量的电子文档可以即时在网上检索浏览,纸张文件通过扫描,手工输入索引信息或OCR识别后同样可以批量的转换成PDF文件和自动入库。
百灵鸟文挡管理系统(DIMS)是一个功能强大的文档管理辅助系统。区别与其他文档管理系统,他能将文档基本信息和文档附件(电子文挡,扫描图片)一起管理。能对文档分类,设置访问权限,支持模糊查询,能很好的支持多用户多权限的管理要求。超级用户可以设置文档类型,设置用户、角色、权限管理,设置部门。管理员可以添加、删除、修改文档。而普通人员仅仅能查看文档。本软件有单机版和网络版本。单机版采用acess数据库,网络版本采用大型数据库SQL Server2000。
我们的文档管理系统吸取了常用文档管理系统中中比较常用的功能,包括编辑、修改、浏览、查找等常用功能,而且具备清晰的目录结构,便于文档的归档和查询。也可以自己添加、删除目录,也可以向目录下层添加子目录。还可以通过标题、关键字、作者等索引信息进行文档的检索。
2文档管理系统应用设计
2.1 可行性分析
可行性分析(Feasibility Analysis)也称为可行性研究,是在系统调查的基础上,针对新系统的开发是否具备必要性和可能性,对新系统的开发从技术、经济、社会的方面进行分析和研究,以避免投资失误,保证新系统的开发成功。可行性研究的目的就是用最小的代价在尽可能短的时间内确定问题是否能够解决。该系统的可行性分析包括以下几个方面的内容。
经济可行性
主要是对项目的经济效益进行评价,本系统开发经费对于所需单位在经济上是可以接受的,并且本系统实施后可以显著提高工作效率,有助于其实现信息化管理。所以本系统在经济上是可行的。
技术上的可行性分析
主要分析技术条件能否顺利完成开发工作,硬、软件能否满足开发者的需要等。该管理系统前台采用vc++做为开发语言,后台用access作为其数据库。Vc++的可视化编程以及access的广泛适用性,系统的软件开发平台已成熟可行。硬件方面,科技飞速发展的今天,硬件更新的速度越来越快,容量越来越大,可靠性越来越高,价格越来越低,其硬件平台完全能满足此系统的需要。
综上所述,此系统开发目标已明确,在技术和经济等方面都可行,并且投入少、见效快。因此系统的开发是完全可行的
2.2开发工具介绍
Visual C++提供了一个支持可视化编程的集成开发环境:Visual Studio(又名Developer Studio)。Developer Studio是一个通用的应用程序集成开发环境,它不仅支持Visual C++,还支持Visual Basic,Visual J++,Visual InterDev等Microsoft系列开发工具。Developer Studio包含了一个文本编辑器、资源编辑器、工程编译工具、一个增量连接器、源代码浏览器、集成调试工具,以及一套联机文档。使用Developer Studio,可以完成创建、调试、修改应用程序等的各种操作。
Developer Studio采用标准的多窗口Windows用户界面,并增加了一些新特性,使得开发环境更易于使用,用户很容易学会它的使用方法。可视化技术是当前发展迅速并引人注目的技术之一,它的特点是把原来抽象的数字、表格、功能逻辑等用直观的图形、图象的形式表现出来。可视化编程是它的重要应用之一。所谓可视化编程,就是指:在软件开发过程中,用直观的具有一定含义的图标按钮、图形化的对象取代原来手工的抽象的编辑、运行、浏览操作,软件开发过程表现为鼠标点击按钮和拖放图形化的对象以及指定对象的属性、行为的过程。这种可视化的编程方法易学易用,而且大大提高了工作效率。
2.2.1数据库说明
电子计算机数据库系统的萌芽出现于60年代。当时计算机开始广泛地应用于数据管理,对数据的共享提出了越来越高的要求。传统的文件系统已经不能满足人们的需要。能够统一管理和共享数据的数据库管理系统(DBMS)应运而生。顾名思义,数据库通常指特定的信息集合,而数据库管理系统是对数据库进行管理和控制的软件。这些管理和控制功能主要包括数据的定义、数据存取和修改、数据库的运行管理、数据库的建立和维护等。除了功能方面的要求外,对于数据库系统性能方面也有一定要求,其中之一就是能够及时准确地满足多个用户的并发存取操作,另外还有能够保证事务的原子性、时刻保持数据的一致性、要求在硬件和操作系统正常工作的情况下独立的并发操作互不影响、不丢失数据。
数据模型是数据库系统的核心和基础,通常由数据结构、数据操作和完整性约束3部分组成。各种DBMS软件都是基于某种数据模型的。所以通常也按照数据模型的特点将传统数据库系统分成网状数据库、层次数据库和关系数据库3类。
网状数据库
最早出现的是网状DBMS。网状模型中以记录为数据的存储单位。记录包含若干数据项。网状数据库的数据项可以是多值的和复合的数据。每个记录有一个惟一地标识它的内部标识符,称为码(DatabaseKey,DBK),它在一个记录存入数据库时由DBMS自动赋予。DBK可以看作记录的逻辑地址,可作记录的替身,或用于寻找记录。网状数据库是导航式(Navigation)数据库,用户在操作数据库时不但说明要做什么,还要说明怎么做。例如在查找语句中不但要说明查找的对象,而且要规定存取路径。
网状数据库模型对于层次和非层次结构的事物都能比较自然的模拟,在关系数据库出现之前网状DBMS要比层次DBMS用得普遍。在数据库发展史上,网状数据库占有重要地位。
层次数据库
最早出现的是网状DBMS。网状模型中以记录为数据的存储单位。记录包含若干数据项。网状数据库的数据项可以是多值的和复合的数据。每个记录有一个惟一地标识它的内部标识符,称为码(DatabaseKey,DBK),它在一个记录存入数据库时由DBMS自动赋予。DBK可以看作记录的逻辑地址,可作记录的替身,或用于寻找记录。网状数据库是导航式(Navigation)数据库,用户在操作数据库时不但说明要做什么,还要说明怎么做。例如在查找语句中不但要说明查找的对象,而且要规定存取路径。
网状数据库模型对于层次和非层次结构的事物都能比较自然的模拟,在关系数据库出现之前网状DBMS要比层次DBMS用得普遍。在数据库发展史上,网状数据库占有重要地位。
关系数据库
一、关系模型的建立
网状数据库和层次数据库已经很好地解决了数据的集中和共享问题,但是在数据独立性和抽象级别上仍有很大欠缺。用户在对这两种数据库进行存取时,仍然需要明确数据的存储结构,指出存取路径。而后来出现的关系数据库较好地解决了这些问题。
关系数据模型提供了关系操作的特点和功能要求,但不对DBMS的语言给出具体的语法要求。对关系数据库的操作是高度非过程化的,用户不需要指出特殊的存取路径,路径的选择由DBMS的优化机制来完成。关系数据模型是以集合论中的关系概念为基础发展起来的。关系模型中无论是实体还是实体间的联系均由单一的结构类型--关系来表示。在实际的关系数据库中的关系也称表。一个关系数据库就是由若干个表组成。
二、SQL语言概述
SQL(Structure Query Language,结构化查询语言)是在数据库系统中应用广泛的数据库查询语言,它包括了数据定义(Data Defintion)、查询(Data Query)、操纵(Data Manipulation)和控制(Data Control)4种功能。SQL的主要功能就是同个各类数据库建立联系,进行沟通。SQL语言由于功能强大,使用方便灵活,语言简洁易学,深受广大数据库用户和数据库开发人员的欢迎。
1986年10月美国国家标准化学会(ANSI)批准将SQL作为.美国数据库的语言标准,随后国际标准化组织(ISO)也作出了同样的决定。SQL成为国际标准语言后,许多数据库软件都支持SQL语言,例如,Oracle、Sybase 、FoxPro 、Access等,使SQL成为数据库主流语言。
在SQL语言中有两个基本概念:基本表和视图。基本表是本身独立存在的表,在SQL中一个关系就对应一个表。一个基本表对应一个存储文件,一个表可以带若干索引,索引也存放在存储文件中。而视图是从一个或几个基本表中导出来的表。它本身不独立存储在数据库中,即数据库中存放视图的定义而不存放视图对应的数据,这些数据仍存放在导出视图的基本表中,因此视图是一个虚表。视图在概念上与基本表等同,用户可以在视图上再定义视图。
常用的SQL语句包括Select 、Insert、 Update 、Delete 、Create及Drop等。
2.2.2 Access功能介绍
Access是Office系列软件中用来专门管理数据库的应用软件。数据库管理系统分为两类:文件管理系统和关系型管理系统。Access应用程序就是一种功能强大且使用方便的关系型数据库管理系统,一般也称关系型数据库管理软件。它可运行于各种Microsoft Windows系统环境中,由于它继承了Windows的特性,不仅易于使用,而且界面友好,如今在世界各地广泛流行。它并不需要数据库管理者具有专业的程序设计水平,任何非专业的用户都可以用它来创建功能强大的数据库管理系统。
Access使用标准的SQL(Structured Query Language,结构化查询语言)作为它的数据库语言,从而提供了强大的数据处理能力和通用性,使其成为一个功能强大而且易于使用的桌面关系型数据库管理系统和应用程序生成器。
此外,Access 2002还利用Office套件共享的编程语言VBA(Visual Basic for Application)进行高级操作控制和复杂的数据操作。
Access与其他数据库开发系统之间显著的区别就是:用户不用编写代码,就可以在很短的时间里开发出一个功能强大而且相当专业的数据库应用程序,并且这一过程是完全可视的,如果给它加上一些简短VBA代码,那么开发出的程序与专业程序员潜心开发的程序一样。
Access的主要优点是不用携带向上兼容的软件。无论是对于有经验的数据库设计人员,还是那些刚刚接触数据库管理系统的新手,都会发现Access数据库所提供的各种工具既非常实用又非常方便,同时还能够获得高效的数据处理能力。
Access的主要特点如下:
(1)具有方便实用的强大功能。Access用户不用考虑构成传统PC数据库的多个单独的文件。
(2)可以利用各种图例快速获得数据。
(3)可以利用报表设计工具,非常漂亮地生成数据报表,而不需要编程。
(4)能够处理多种数据类型。Access可以对诸如DBASE FoxBase FoxPro及Btrieve等格式的数据进行访问。
(5)采用OLE技术,能够方便创建和编辑多媒体数据库,包括文本、声音、图象和视频等对象。
(6) Access支持ODBC标准的SQL数据库的数据。
(7) 计过程自动化,大大提高了数据库的工作效率。采用窗体向导和报表向导,用户只要按照向导就可以自动生成窗体和报表。采用宏可以自动完成数据库的管理例程。
(8) 具有较好的集成开发功能。可以采用VBA(Visual Basic Application)编写数据库应用程序。
(9) 提供了断点设置,单步执行等调试功能。能够像Word2000那样自动进行语法
检查和错误诊断。
(10) 与Internet的集成。Access进一步完善了将Internet集成到整个办公室的桌面操作环境。
(11) 可以将数据库应用程序的建立移进用户环境,并使最终用户和应用程序开发者之间的关系淡化。
总之,Access发展到现在已经向用户展示出易于使用和功能强大的特性。
作为一个数据库管理系统,Access通过各种数据库对象来管理信息。Access数据库由
数据库对象和组两部分组成,其中对象又分为7种。这些数据库对象包括:表、对象、查询、窗体、报表、数据访问页、宏、和模块。当打开一个数据库时,这些Access的数据库对象在界面左边很醒目的显示。
Access所提供的这些对象都放在同一个数据库文件(扩展名为.mdb)中,而不是象其他PC数据库那样分别存放在不同的文件中。这样就方便了数据管理。不同的数据库对象在数据库中起着不同的作用。例如,用表来存储数据,用查询来检索符合指定条件的数据,通过窗体来浏览或更新表中的数据,用报表以特定的方式来分析和打印数据。
Access中各个对象之间的关系如图1.1.3所示。表是数据库的核心与基础,存放着数据库中的全部数据。报表、数据、查询和窗体都是从数据库中或得信息,以实现用户的某一特定需求,例如,查找、计算统计、打印、编辑修改等。窗体可以提供一种良好的用户操作界面,通过 它可以直接或间接地调用宏或模块,并执行查询、打印、预览、计算等功能,甚至可以对数据库进行修改。
图3.2.2.2 Access数据库对话框
一、表
存储数据的容器,是关系数据库系统的基础。表以行列格式存储数据项,这一点和电子表格有些类似。表中的单个信息单元(列)称为字段,在表的顶部可以看到这些字段名,字段是Access信息的最基本载体,说明了一条信息在某一方面的属性;表的一行中所有数据字段的集合,称为记录一条记录。就是一个完整的信息在数据库中,应该为不同的主题建立单个表,这样可以提高数据库的工作效率,并可以减少因数据输入而产生的错误。用户可以从其他的应用系统(如 dBASE、FoxPro、Paradox)、客户/服务器数据库(如 SQL Server)以及电子表格(如Excel工作表和Lotus1-2-3)中导入表。Access可以同时打开1024个表。
二、查询
显示从多个表(最多为16个)中选取的数据。通过使用查询,用户可以指定如何表示数据,选择构成查询的表,并可以从所选表中提取出最多255个特定的字段。用户可以通过指定要查询数据的条件来决定显示的数据项。
查询是数据库设计目的的体现,数据库建完以后,数据只有被使用者查询,才能真正体现它的价值。查询是用来操作数据库中的记录对象,利用它可以按照一定的条件或准则从一个或多个表中筛选出需要操作的字段,并可以将它们集中起来,形成所谓的动态数据集,这个动态数据集显出用户希望同时看到的来自一个或多个表中的字段,并显示在一个虚拟的数据表窗口中。用户可以浏览、查询、打印,甚至是修改这个动态数据集中的数据,Access会自动将所做的任何修改反映到对应的表中。执行某个查询后,用户可以对查询的结果进行编辑或分析,并可将查询结果作为其他数据库对象的数据源。
查询到的数据记录集合称为查询的结果集,结果集以二维表的形式显示出来,但他们不是基本表。每个查询只记录该查询的查询操作方式,这样,每进行一次查询操作,其结果集显示的都是基本表中当前存储的实际数据,它反映的是查询的那个时刻数据表的存储情况,查询的结果是静态的。
使用查询可以按照不同的方式查看、更改、和分析数据,也可以使用查询作为窗体、报表和数据访问页的记录源。
三、窗体
窗体是Access数据库对象中最具灵活性的一个对象,其数据源可以是表或查询。在
窗体中可以显示数据表中的数据,可以将数据库中的表连接到窗体中,利用窗体作为输入记录的界面。通过在窗体中插入按钮,可以控制数据库程序的执行过程,可以说窗体是数据库与用户进行交互操作的最好界面。利用窗体,能够从表中查询提取所需的数据,并将其显示出来。通过在窗体中插入宏,用户可以把Access的各个对象很方便地联系起来。
窗体中可以包含图片、图形、声音、视频等多种对象,也可以包含VBA代码来提供事件处理。子窗体是包含于主窗体中的窗体,主要是用来简化用户的操作。
四、报表
数据库应用程序通常要进行打印输出,在Access中,如果要打印输出数据,使用报表是很有效的方法。报表可以将数据库中需要的数据提取出来进行分析、整理、和计算,并将数据以格式化的方式发送到打印机。用户可以在一个表或查询的基础上来创建一个报表,也可以在多个表或查询的基础上来创建报表。利用报表不仅可以创建计算字段,而且可以对记录进行分组以便计算出各组数据的汇总结果等。在报表中,可以控制显示的字段、每个对象的大小和显示方式,并可以按照所需的方式来显示相应的内容。
五、数据访问页
数据访问页是在Access2000时才增加的数据库对象,它是一种特殊类型的WEB页,用户可以在此WEB页中与Access数据库中的数据进行联接,查看、修改Access数据库中的数据,为通过网络进行数据发布提供了方便。数据访问页在一定程度上集成了Internet Explorer 浏览器和FrontPage编辑器的功能。
六、宏
Microsoft office 提供的所有工具中都提供了宏的功能,宏实际上是一系列操作的集合,其中每个操作都能实现特定的功能,例如,打开窗体、生成报表、保存修改等。在日常工作中,用户经常需要重复大量的操作,利用宏可以简化这些操作,使大量的重复性操作自动完成,从而使管理和维护Access数据库更加简单。现在宏已经过时了,Access 2002之所以支持宏,是为了能够与早期的 Access 版本所创建的数据库应用系统保持兼容。Microsoft建议在Access应用系统中采用VBA代码来进行事件的处理,这一原则在Office系列中均适用。
七、模块
模块是将Visual Basic for Application 声明和过程作为一个单元进行保存的集合,是
应用程序开发人员的工作环境,如图1.22所示。模块中的每一个过程都是一个函数过程或字程序。通过将模块与窗体、报表等Access对象相联系,可以建立完整的数据库应用程序。
原则上说,使用Access,用户不需编程就可以创建功能强大的数据库应用程序,但是通过在Access中编写Visual Basic 程序,用户可以编出复杂的、运行效率更高的数据库应用程序。模块的主要作用就是建立复杂的VBA程序以完成宏等不能完成的任务。
Access 2000提供的上述七种对象分工极为明确,从功能和彼此间的关系角度考虑,这七种对象可以分为三个层次:第一层次是表对象和查询对象,它们是数据库的基本对象,用于在数据库中存储数据和查询数据。第二层次是窗体对象、报表对象和数据访问页,它们是直接面向用户的对象,用于数据的输入输出和应用系统的驱动控制。第三层次是宏对象和模块对象,它们是代码类型的对象,用于通过组织宏操作或编写程序来完成复杂的数据库管理工作并使得数据库管理工作自动化。
2.2.3几种VC++数据库开发技术的比较
从功能简单的数据库(如Jet Engine)到复杂的大型数据库系统(如oracle),VC++6.0都提供了一些编程接口。本文主要介绍以下五种:
1.ODBC API;
2.MFC ODBC类;
3.MFC DAO类;(数据访问对象)
4.MFC的OLE/DB;
5.ActiveX数据对象(ADO)。
1.开放数据库连接(ODBC API):提供了一个通用的编程接口,允许程序与多种不同的数据库连接。它为Oracle,SQL Server,MS Excel等都提供了驱动程序,使得用户可以使用SQL语句对数据库进行直接的底层功能操作。在使用ODBC API时,用户须引入的头文件为"sql.h","sqlext.h","sqltypes.h"。用ODBC API创建数据库应用程序遵循一定的基本步骤:
第一步是分配ODBC环境,使一些内部结构初始化。完成这一步,须分配一个SQLHENV类型的变量在ODBC环境中做句柄使用。
第二步是为将要使用的每一个数据源分配一个连接句柄,由函数SQLALLocHandle()完成。
第三步是使用SQLConnect()把连接句柄与数据库连接,可以先通过SQLSetConnectAttr()设置连接属性。
然后就可以进行SQL语句的操作,限于篇幅,相关的函数就不具体介绍了,读者可以参考相关书籍。
操作完成后,用户取回相应的结果,就可以取消与数据库的连接。
最后需要释放ODBC环境。
ODBC API的特点是功能强大丰富,提供了异步操作,事务处理等高级功能,但相应的编程复杂,工作量大。
2.MFC ODBC类:MFC1.5后的版本里引入封装了ODBC功能的类。通过这些类提供与ODBC的接口,使得用户可以不须处理ODBC API中的繁杂处理就可以进行数据库操作。主要的MFC ODBC类如下。
CDatabase类:一个CDatabase对象表示一个到数据源的连接,通过它可以操作数据源。应用程序可使用多个CDatabase对象:构造一个对象并调用OpenEx()成员函数打开一个连接。接着构造CRecordSet对象以操作连接的数据源,并向CDatabase对象传递记录集构造程序指针。完成使用后用Close()成员函数销毁CDatabase对象。一般情况下并不需要直接使用CDatabase对象,因为CRecordSet对象可以实现大多数的功能。但是在进行事务处理时,CDatabase就起到关键作用。事务(Transaction)指的是将一系列对数据源的更新放在一起,同时提交或一个也不提交,为的是确保多用户对数据源同时操作时的数据正确性。
CRecordSet类:一个CRecordSet对象代表一个从数据源选择的一组记录的集合-记录集。记录集有两种形式:snapshot和dynaset。前者表示数据的静态视图,后者表示记录集与其他用户对数据库的更新保持同步。通过CRecordSet对象,用户可以对数据库中的记录进行各种操作。
CRecordView类:CRecordView对象是在空间中显示数据库记录的视图。这种视图是一种直接连到一个CRecordSet对象的格式视图,它从一个对话框模板资源创建,并将CRecordSet对象的字段显示在对话框模板的控件里。对象利用DDX和RFX机制,使格式上的控件和记录集的字段之间数据移动自动化,也就是说,用户甚至不要编写一行代码就可以实现简单的数据库记录查看程序。
CDBException类:由Cexception类派生,以三个继承的成员变量反映对数据库操作时的异常:
m_nRetCode:以ODBC返回代码(SQL_RETURN)的形式表明造成异常的原因。
m_strError:字符串,描述造成抛出异常的错误原因。
m_strStateNativeOrigin:字符串,用以描述以ODBC错误代码表示的异常错误。
MFC数据库类成员函数都能抛出CDBException类型的异常,所以在代码对数据库进行操作后监测异常是正确做法。
MFC ODBC类在实际开发中应用最广,因为它功能丰富,操作相对简便。
3.MFC DAO(数据访问对象)编程:DAO用于和微软的Access数据库接口。在数据库应用程序如果只需与Access数据库接口时,使用DAO编程较方便。其主要类如下。
CDaoWorkspace:CDaoWorkspace对象可以让一个用户管理从登陆到离开期间,指定的密码保护的数据库会话全过程。大多数情况下不要多个工作区也不要创建明确的工作区对象。因为在打开数据库和记录集对象时,它们可以使用DAO缺省工作区。
CDaoDatabase:代表一个连接,类似上述CDatabase类。
CDaoRecordSet:用来选择记录集并操作,类似上述CRecordSet类。
CDaoRecordView:类似上述CRecordView类。
CDaoException:类似上述CDBException类。
CDaoTableDef:表示基本表或附加表的定义。每个DAO数据库对象包括一个称为TableDef的收集,包含所有存储的DAO表定义对象。CDaoTableDef对象可以用来控制表定义。
CDaoQueryDef:CDaoQueryDef对象表示了一个查询定义(querydef)。
CDaoFieldExchange:支持数据库类使用的DAO字段交换(DFX)例程。也可处理事务,类似MFC ODBC类。
MFC DAO仅用来支持Access数据库,应用范围相对固定。
4.OLE DB:OLE DB在数据提供程序和用户之间提供了灵活的组件对象模型(COM)接口,这种灵活性有时会使得操作复杂化。OLE DB框架定义了应用的三个基本类。
数据提供程序Data Provider:拥有自己的数据并以表格形式显示数据的应用程序。提供OLE DB的行集COM接口,期显示范围可以从单一数据表格的简单提供者知道更复杂的分布式数据库系统。
使用者Consumers:使用OLE DB接口对存储在数据提供程序中的数据进行控制的应用程序。用户应用程序归为使用类。
服务提供程序Service Provider:是数据提供程序和使用者的组合。服务提供程序没有自己的数据,但使用
OLE DB使用者接口来访问存储在数据提供程序中的数据。然后,服务提供程序通过打开数据提供程序接口使得数据对使用者有效。服务提供程序常用于向应用程序提供高层次服务,比如高级分布式查询。
OLE DB编程时,用户使用组件对象开发应用程序。这些组件有:
枚举器:用于列出可用的数据源;
数据源:代表单独的数据和服务提供程序,用于创建对话;
对话:用于创建事务和命令;
事务:用于将多个操作归并为单一事务处理;
命令:用于向数据源发送文本命令(SQL),返回行集;
错误:用于获得错误信息。
5.ActiveX数据对象(ADO):是微软提供的面向对象的接口,与OLE DB类似,但接口更简单,具有更广泛的特征数组和更高程度的灵活性。ADO基于COM,提供编程语言可利用的对象,除了面向VC++,还提供面向其他各种开发工具的应用,如VB,VJ等。ADO在服务器应用方面非常有用,特别是对于动态服务器页面ASP(Active Server Page)。
ADO对象结构类似于OLE DB,但并不依靠对象层次。大多数情况下,用户只需要创建并只使用需要处理的对象。下面的对象类组成了ADO接口。
Connection:用于表示与数据库的连接,以及处理一些命令和事务。
Command:用于处理传送给数据源的命令。
Recordset:用于处理数据的表格集,包括获取和修改数据。
Field:用于表示记录集中的列信息,包括列值和其他信息。
Parameter:用于对传送给数据源的命令之间来回传送数据。
Property:用与操作在ADO中使用的其他对象的详细属性。
Error:用于获得可能发生的错误的详细信息。
在VC++使用ADO需要进行COM操作,详细方法在此就不赘述了。
在当今流行的分布式开发环境下,VC++6.0在数据库开发方面有较强的优势,学会在不同的场合选用不同的技术,对开发人员来说是必要的技术。
3齐心文档管理系统的设计和实现
3.1齐心数据库访问的实现
3.1.1齐心数据库访问技术
MFC DAO 类处理 DAO 的方式与 Windows 编程所用的 MFC 类处理Windows API 的方式很相似:MFC 将 DAO 功能封装(即“包装”)在若干个类中,这些类密切对应于 DAO 对象。CDaoWorkspace 类封装 DAO 工作区对象,CDaoRecordset 类封装 DAO 记录集对象,CDaoDatabase 类封装 DAO 数据库对象等。
MFC 对 DAO 的封装很彻底,但并不是完全一对一。大部分主要的 DAO 对象确实对应于 MFC 类,而且 MFC 类一般提供对基础 DAO 对象的属性和方法的完全访问。但是某些 DAO 对象并不是这样,包括字段、索引、参数和关系。相反,某些适当的 MFC 类通过成员函数提供接口,而用户可以通过这些接口访问 DAO 对象,例如:
· 记录集对象的字段
· 表索引或表字段
· querydef 的参数
· 数据库表之间定义的关系
VC++的MFC类库为编程者编制好了对数据库操作的类,编程者可以使用向导建立一个与数据库联结并对数据库进行操作的应用程序,不需要编制任何代码,这无疑为编程人员提供了一个捷径。但是,使用向导时只有选用基于单文档或多文档的项目才能选择数据源与指定的的数据库相连,对用向导生成的基于对话框的应用程序不提供数据库的支持。即使是基于单文档或多文档的应用程序,当需要一些特殊的操作,例如,打开一个表,要求返回满足一定条件的记录集时,MFC并没有提供完全符合要求的现成函数。如果能利用MFC所提供的数据库操作,再加上自己设计的函数,也就是说,设计一个对数据库操作的类,在程序中手工加入这个类,那么就可以在基于对话框的应用程序中实现对数据库的操作,而且,也可以针对自己应用程序的具体需要来设计类的函数,为特定功能的实现提供了很大的方便。
在本程序种,我们就自定义了一个数据库操作类——CDBOper。在一个涉及数据库操作的应用程序中,常用到的MFC类有CdaoDatabase类、CdaoTableDef类、CdaoRecordset类和 CdaoQueryDef类。当对数据库进行操作时,需要先打开数据库,然后打开数据库中的表,再得到查询集和记录集。在自己定义的类中综合这四个类的操作,设计一个打开表得到查询集和记录集的函数。以后,在应用程序中使用该类时只需包含该类的头文件,所设计的函数就可以直接调用了。
3.1.2数据访问编程
下表显示 DAO 对象如何对应于 MFC 对象。“MFC 类和对应的 DAO 对象”显示了 MFC 类及其封装的 DAO 对象。“MFC 如何管理未映射到类的 DAO 对象”显示了 MFC 如何处理未直接映射到 MFC 类的 DAO 对象。
MFC 类和对应的 DAO 对象
类 |
DAO 对象 |
备注 |
CDaoWorkspace |
工作区 |
管理事务空间并且提供对数据库引擎的访问。 |
CDaoDatabase |
数据库 |
表示到数据库的连接。 |
CDaoTableDef |
Tabledef |
用来检查并操作表结构。 |
CDaoQueryDef |
Querydef |
用来存储数据库中的查询。可以从 querydef 中创建记录集或者使用 querydef 执行操作或 SQL 传递查询。 |
CDaoRecordset |
记录集 |
用来管理结果集,它是基于表或查询选定的记录集。 |
CDaoException |
错误 |
MFC 通过引发此类异常来响应所有DAO错误。 |
CDaoFieldExchange |
无 |
管理数据库记录与记录集字段数据成员之间的数据交换。 |
MFC 如何管理未映射到类的 DAO 对象
DAO 对象 |
MFC 如何管理它 |
字段 |
CDaoTableDef 类对象和 CDaoRecordset 类对象封装字段并且提供用来添加、删除和检查字段的成员函数。 |
索引 |
CDaoTableDef 类对象和 CDaoRecordset 类对象封装索引并且提供用来管理索引的成员函数。Tabledef 可以添加、删除和检查索引。Tabledef 和记录集可以设置或获取当前活动的索引。 |
参数 |
CDaoQueryDef 类对象封装参数并且提供用来添加、删除和检查参数以及获取和设置参数值的成员函数。 |
关系 |
CDaoDatabase 类对象封装关系并且提供用来添加、删除和检查关系的成员函数。 |
DAO用于和微软的Access数据库接口。在数据库应用程序如果只需与Access数据库接口时,使用DAO编程较方便。其主要类如下。
CDaoWorkspace:CDaoWorkspace对象可以让一个用户管理从登陆到离开期间,指定的密码保护的数据库会话全过程。大多数情况下不要多个工作区也不要创建明确的工作区对象。因为在打开数据库和记录集对象时,它们可以使用DAO缺省工作区。
CDaoDatabase:代表一个连接,类似上述CDatabase类。
CDaoRecordSet:用来选择记录集并操作,类似上述CRecordSet类。
CDaoRecordView:类似上述CRecordView类。
CDaoException:类似上述CDBException类。
CDaoTableDef:表示基本表或附加表的定义。每个DAO数据库对象包括一个称为TableDef的收集,包含所有存储的DAO表定义对象。CDaoTableDef对象可以用来控制表定义。
CDaoQueryDef:CDaoQueryDef对象表示了一个查询定义(querydef)。CDaoFieldExchange:支持数据库类使用的DAO字段交换(DFX)例程。也可处理事务,类似MFC ODBC类。
MFC DAO仅用来支持Access数据库,应用范围相对固定。
VC++的MFC类库为编程者编制好了对数据库操作的类,编程者可以使用向导建立一个与数据库联结并对数据库进行操作的应用程序,不需要编制任何代码,这无疑为编程人员提供了一个捷径。但是,使用向导时只有选用基于单文档或多文档的项目才能选择数据源与指定的的数据库相连,对用向导生成的基于对话框的应用程序不提供数据库的支持。即使是基于单文档或多文档的应用程序,当需要一些特殊的操作,例如,打开一个表,要求返回满足一定条件的记录集时,MFC并没有提供完全符合要求的现成函数。如果能利用MFC所提供的数据库操作,再加上自己设计的函数,也就是说,设计一个对数据库操作的类,在程序中手工加入这个类,那么就可以在基于对话框的应用程序中实现对数据库的操作,而且,也可以针对自己应用程序的具体需要来设计类的函数,为特定功能的实现提供了很大的方便。
在本程序种,我们就自定义了一个数据库操作类——CDBOper。在一个涉及数据库操作的应用程序中,常用到的MFC类有CdaoDatabase类、CdaoTableDef类、CdaoRecordset类和 CdaoQueryDef类。当对数据库进行操作时,需要先打开数据库,然后打开数据库中的表,再得到查询集和记录集。在自己定义的类中综合这四个类的操作,设计一个打开表得到查询集和记录集的函数。以后,在应用程序中使用该类时只需包含该类的头文件,所设计的函数就可以直接调用了。
3.2 系统实现
3.2.1 系统功能分析
文档管理系统的主界面如下:
文档管理系统主要有以下几项功能要求:
1.文档资料的入库
实现对指定文件的添加入库功能
void CDlgFileAdd::OnOK()
{
// TODO: Add extra validation here
UpdateData();
if (m_strType.IsEmpty() || m_strFileName.IsEmpty())
{
AfxMessageBox("请正确输入信息!!!");
return ;
}
HANDLE hFile;
hFile = CreateFile(m_strFileName.GetBuffer(0), // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
AfxMessageBox("Could not open file");
return ;
}
DWORD dwSize = GetFileSize(hFile,NULL);
CloseHandle(hFile);
COleDateTime dateTest;
dateTest = COleDateTime::GetCurrentTime();
CString strTime;
strTime.Format("%d-%d-%d %d:%d:%d",dateTest.GetYear(),dateTest.GetMonth(),\
dateTest.GetDay(),dateTest.GetHour(),dateTest.GetMinute(),dateTest.GetSecond());
int iId = CDBOper::GetDBOper()->GetTypeId(m_strType.GetBuffer(0));
if (iId == -1)
{
AfxMessageBox("得到文档类型错误!!!");
return;
}
CString strSql;
strSql.Format("Insert into tblfiles (type_id,file_name,addtime,file_size,file_desc,file_dir) values ('%d','%s','%s','%d','%s','%s')",\
iId,m_strFileName,strTime,dwSize,m_strDesc,m_strDir);
if(!CDBOper::GetDBOper()->InsertDB(strSql.GetBuffer(0)))
{
AfxMessageBox("数据库操作失败");
return ;
}
m_dirView->AddData(strName.GetBuffer(0),strPath.GetBuffer(0));
CDialog::OnOK();
}
添加文件界面如下:
2.文档资料的打开
通过Microsoft Web浏览器控件来实现对,pdf,doc等文件的打开浏览。
本程序通过类CShowDocFileView来实现的
代码如下:
void CDirFileView::OpenFile()
{
CTreeCtrl & myTree = this->GetTreeCtrl();
HTREEITEM htiNext = myTree.GetSelectedItem();
HTREEITEM hRoot;
if (htiNext != NULL)
{
if ((hRoot = myTree.GetParentItem(htiNext)) == NULL) // 如果是文件类型,则展开
{
myTree.Expand(htiNext,TVE_EXPAND | TVE_COLLAPSERESET );
}
else // 在视图文件中打开文件
{
CString strTemp = myTree.GetItemText(htiNext);
((CMainFrame*)AfxGetMainWnd())->m_showView->ShowFileContext(strTemp.GetBuffer(0));
}
}
}
3.文档资料的属性显示
查看文件资料的添加时间,文件存储路径,文件名,及相关属性。这些相关信息都通过结构FILEPROPER来实现的
属性显示代码如下:
void CMainFrame::OnEditProperties()
{
m_dirView->FileProperties();
}
4.文档资料和文档类型的查询
文档类型查询:
void CMainFrame::OnTypeQuert()
{
// TODO: Add your command handler code here
CDlgFileTypeQuert dlg;
dlg.DoModal();
}
其界面如下:
文件查询:
void CMainFrame::OnEditQuert()
{
// TODO: Add your command handler code here
CDlgQuertFiles dlg;
CString strSql;
CString strTemp;
strTemp = "select a.type_name,b.file_name from tbltype a,tblfiles b where a.type_id = b.type_id";
if(dlg.DoModal() == IDOK)
{
if (!dlg.m_strExt.IsEmpty())
{
if (!dlg.m_strName.IsEmpty())
{
strSql.Format("%s and a.type_name = '%s' and b.file_name ='%s' order by type_name",\
strTemp,dlg.m_strExt,dlg.m_strName);
}
else
{
strSql.Format("%s and a.type_name = '%s' order by type_name",strTemp,dlg.m_strExt);
}
}
else
{
if (!dlg.m_strName.IsEmpty())
{
strSql.Format("%s and b.file_name = '%s' order by type_name",strTemp,dlg.m_strName);
}
}
m_dirView->SetDirData(strSql);
}
}
其界面如下:
5.文档目录的添加
void CDlgFileTypeAdd::OnOK()
{
// TODO: Add extra validation here
UpdateData();
if (m_strType.IsEmpty())
{
AfxMessageBox("请输入文件归档类型!!!");
return ;
}
CString strSql;
strSql.Format("insert into tbltype (type_name,type_desc) values ('%s','%s')",m_strType,m_strDesc);
if(CDBOper::GetDBOper()->InsertFileType(strSql.GetBuffer(0)))
CDialog::OnOK();
}
其界面如下:
3.2.2 系统功能模块设计
根据系统功能的要求,可以将系统分解成几个功能模块来分别设计,功能模块如下图所示:
3.3齐心系统文件浏览的实现
“Microsoft Web浏览器”控件随Visual C++开发环境一起安装到系统。从“Project”菜单下“Add To Project”弹出菜单的“Components and Controls…”子菜单弹出“Components and Controls Gallery”对话框,进入“Registered ActiveX Controls”目录并选中“Microsoft Web浏览器”控件,点击“Insert”按钮将其添加到VC++开发环境的控件工具栏中。
通常对ActiveX控件的使用多是在资源视图中将指定的ActiveX控件拖拽到相应的对话框中,并完成对其属性的设置和对事件处理函数的添加。但由于本程序应用“Microsoft Web浏览器”控件的目的是为了浏览PDF和Word等格式的文档,因此应用程序框架采取文档视图结构比较合适,在这种情况下显然不能再以传统方式创建控件而应通过代码来完成动态创建。
在将 “Microsoft Web浏览器”控件插入到工程后,派生于CWnd类的CWebBrowser2类被添加到工程,它提供了一个可供重载使用的虚函数Create()和一个类成员函数Create():
virtual BOOL Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName,DWORD dwStyle,const RECT& rect,CWnd* pParentWnd, UINT nID,CCreateContext* pContext = NULL);
BOOL Create(LPCTSTR lpszWindowName,DWORD dwStyle,const RECT& rect, CWnd* pParentWnd, UINT nID,
CFile* pPersist = NULL, BOOL bStorage = FALSE,
BSTR bstrLicKey = NULL);
通过该函数将可以象动态创建编辑框、按钮等标准控件一样动态创建。这里需要特别指出的是,一个“Microsoft Web浏览器”控件只能负责对一个文档的维护,也就是说,在多文档结构的本程序中需要为每一个打开的文档分配一个“Microsoft Web浏览器”控件以进行管理。这在具体实施上,只需在文档或视图类中声明CWebBrowser2类对象即可。下面这段代码在视图类完成,在OnInitialUpdate()函数更新视图时完成对控件的动态创建,创建的控件将占据视图的全部客户区:
CWebBrowser2 m_Web;
……
// 得到客户区
CRect rect;
GetClientRect(&rect);
// 创建控件窗体
m_Web.Create(NULL, WS_CHILD | WS_VISIBLE, rect, this, ID_WORD);
文档的打开显示
本程序在文件打开显示上采取的策略是:由程序框架负责获取需要打开的文件路径,并新建一文档。在视图更新“Microsoft Web浏览器”控件创建完毕后,由CWebBrowser2类成员函数Navigate ()负责对具体文档的维护管理。这部分工作的具体处理代码如下:
// 主框架类:
// 显示打开文件对话框
CFileDialog fileDlg(TRUE, "*.doc", "*.doc", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Word文件(*.doc)|*.doc|PDF文件(*.pdf)|*.pdf|Web页(*.htm)|*.htm|所有文件(*.*)|*.*||", NULL);
if (fileDlg.DoModal() == IDOK)
{
// 得到文件路径
m_sPath = fileDlg.GetPathName();
// 新建文档
PostMessage(WM_COMMAND, ID_FILE_NEW, 0);
}
……
// 视图类:
// 得到并保存要打开的文件路径
m_sFilePath = ((CMainFrame*)AfxGetApp()->GetMainWnd())->m_sPath;
((CMainFrame*)AfxGetApp()->GetMainWnd())->m_sPath = "about:blank";
// 打开指定的文件
m_Web.Navigate(m_sFilePath, NULL, NULL, NULL, NULL);
// 窗体设置为大小可变
m_Web.SetResizable(TRUE);
为了在刷新视图或窗口尺寸变更时能够即使刷新显示,还需要在OnDraw()函数和WM_SIZE消息响应函数OnSize()中添加额外的处理代码:
// 重绘窗口 (OnDraw()函数)
if (m_Web.m_hWnd != NULL)
m_Web.RedrawWindow();
……
void CShowWordView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if (m_Web.m_hWnd != NULL)
{
// 得到新的客户区
CRect rect;
GetClientRect(&rect);
// 设置新的窗口位置
m_Web.SetWindowPos(&wndTop, rect.left, rect.top, rect.Width(), rect.Height(), NULL);
// 重绘窗体
m_Web.RedrawWindow();
}
}
其中,SetWindowPos()函数将重新设置“Microsoft Web浏览器”控件窗口的放置位置以使其能够占据尺寸更改后的文档窗口的全部客户区大小。
程序实际运行效果,不仅能够同时浏览Word格式文档和PDF文档,还能够同时打开、并列显示多个PDF文档(在Acrobat Reader中虽然能够同时打开多个文档但不能并列显示)。这样PDF和Word格式文档文件就能打开,但由于实际是通过CWebBrowser2类来完成具体的文档打开和显示处理的,因此支持的文档格式并不局限于PDF和Word格式,只要符合IE接口规范的任意一种文件格式如HTML、JPEG等,使用本文所述方法同样能够将其打开、显示。本文所述程序在Windows 2000 Professional下由Microsoft Visual C++ 6.0编译运行通过。需要有Microsoft Word 2000和Acrobat Reader 5.0以上版本软件的支持。
附录:
1. 计算机程序
// DirFileView.cpp : implementation of the CDirFileView class
//
#include "stdafx.h"
#include "DocFiles.h"
#include "DocFilesDoc.h"
#include "DirFileView.h"
#include "MainFrm.h"
#include "showDocFilesView.h"
#include "DlgFilePro.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDirFileView
IMPLEMENT_DYNCREATE(CDirFileView, CTreeView)
BEGIN_MESSAGE_MAP(CDirFileView, CTreeView)
//{{AFX_MSG_MAP(CDirFileView)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
ON_WM_LBUTTONDBLCLK()
ON_WM_CONTEXTMENU()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CTreeView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CTreeView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CTreeView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDirFileView construction/destruction
CDirFileView::CDirFileView()
{
// TODO: add construction code here
}
CDirFileView::~CDirFileView()
{
}
BOOL CDirFileView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CTreeView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CDirFileView drawing
void CDirFileView::OnDraw(CDC* pDC)
{
CDocFilesDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CDirFileView printing
BOOL CDirFileView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CDirFileView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CDirFileView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
void CDirFileView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate();
((CMainFrame *)AfxGetMainWnd())->m_dirView = this;
CTreeCtrl & myTree = this->GetTreeCtrl();
myTree.ModifyStyle(0, TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT);
InitData();
// TODO: You may populate your TreeView with items by directly accessing
// its tree control through a call to GetTreeCtrl().
}
/////////////////////////////////////////////////////////////////////////////
// CDirFileView diagnostics
#ifdef _DEBUG
void CDirFileView::AssertValid() const
{
CTreeView::AssertValid();
}
void CDirFileView::Dump(CDumpContext& dc) const
{
CTreeView::Dump(dc);
}
CDocFilesDoc* CDirFileView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDocFilesDoc)));
return (CDocFilesDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDirFileView message handlers
HTREEITEM CDirFileView::InsertData(HTREEITEM root,char *lpszData)
{
CTreeCtrl & myTree = this->GetTreeCtrl();
HTREEITEM hResult = myTree.InsertItem(lpszData,root);
return hResult;
}
HTREEITEM CDirFileView::CreateRoot(char *lpszData)
{
CTreeCtrl & myTree = this->GetTreeCtrl();
m_root = myTree.InsertItem(lpszData);
return m_root;
}
bool CDirFileView::InitData()
{
// 把数据库记录全读出来
CString strSql;
strSql = "select b.type_name,a.file_name from tblfiles a,tbltype b where a.type_id = b.type_id order by type_name";
SetDirData(strSql);
return true;
}
bool CDirFileView::AddData(char *lpszExtName,char *lpszFileName)
{
CTreeCtrl & myTree = this->GetTreeCtrl();
HTREEITEM hRoot = myTree.GetRootItem();
HTREEITEM htiNext = hRoot;
bool bResult = false;
// check 文件类型是否存在
while(htiNext)
{
CString strTemp = myTree.GetItemText(htiNext);
hRoot = htiNext;
if (lpszExtName == strTemp)
{
bResult = true;
break;
}
htiNext = myTree.GetNextSiblingItem(htiNext);
} //end
// 向树型视图添加一条记录
if (!bResult)
{
hRoot = CreateRoot(lpszExtName); // 文件类型不存在,添加文件类型
}
InsertData(hRoot,lpszFileName); // 添加文件
return true;
}
bool CDirFileView::DelData()
{
CTreeCtrl & myTree = this->GetTreeCtrl();
HTREEITEM htiNext = myTree.GetSelectedItem();
HTREEITEM hRoot;
CString strSql;
if (htiNext != NULL)
{
if ((hRoot = myTree.GetParentItem(htiNext)) == NULL)// 删除一类记录
{
myTree.Expand(htiNext,TVE_EXPAND | TVE_COLLAPSERESET );
CString strTemp = myTree.GetItemText(htiNext);
int iId = CDBOper::GetDBOper()->GetTypeId(strTemp.GetBuffer(0));
if (MessageBox("要完全删除这类文件吗???" + strTemp,"删除",MB_YESNO) == IDYES)
strSql.Format("delete from tblfiles where type_id =%d",iId);
else
return false;
}
else// 删除一条记录
{
CString strRoot = myTree.GetItemText(hRoot);
CString strFile = myTree.GetItemText(htiNext);
int iId = CDBOper::GetDBOper()->GetTypeId(strRoot.GetBuffer(0));
strSql.Format("delete from tblfiles where file_name = '%s' and type_id = %d",\
strFile,iId);
}
if(CDBOper::GetDBOper()->DeleteDB(strSql.GetBuffer(0))) // 数据库删除记录
myTree.DeleteItem(htiNext); // 控件删除记录
}
return false;
}
void CDirFileView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
*pResult = 0;
}
void CDirFileView::OnLButtonDblClk(UINT nFlags, CPoint point) // 打开文件视图
{
// TODO: Add your message handler code here and/or call default
CTreeView::OnLButtonDblClk(nFlags, point);
OpenFile();
}
bool CDirFileView::SetDirData(CString strSql)
{
listQuert listResult;
if (!CDBOper::GetDBOper()->SelectDB(strSql.GetBuffer(0),listResult))
return false;
CTreeCtrl & myTree = this->GetTreeCtrl();
myTree.DeleteAllItems();
listQuert::iterator pos;
for(pos = listResult.begin(); pos != listResult.end();pos++)
{
AddData((*pos).strType.GetBuffer(0),(*pos).strName.GetBuffer(0));
}
return true;
}
void CDirFileView::OnContextMenu(CWnd* pWnd, CPoint point)
{
// TODO: Add your message handler code here
}
bool CDirFileView::FileProperties()
{
// TODO: Add your command handler code here
CTreeCtrl & myTree = this->GetTreeCtrl();
HTREEITEM htiNext = myTree.GetSelectedItem();
HTREEITEM hRoot;
if (htiNext != NULL)
{
if ((hRoot = myTree.GetParentItem(htiNext)) == NULL) // 如果是文件类型,则展开
{
myTree.Expand(htiNext,TVE_EXPAND | TVE_COLLAPSERESET );
}
else // 在视图文件中打开文件
{
CString strType = myTree.GetItemText(hRoot);
CString strFile = myTree.GetItemText(htiNext);
CString strSql,strTemp;
strTemp = "select a.file_name,a.file_size,a.addtime,a.file_desc,a.file_dir,b.type_name,b.type_desc from tblfiles a, tbltype b";
strSql.Format("%s where a.type_id = b.type_id and b.type_name = '%s' and a.file_name = '%s'",\
strTemp,strType,strFile);
FILEPROPER result;
if(CDBOper::GetDBOper()->SelectFileProper(strSql.GetBuffer(0),result))
{
CDlgFilePro dlg;
dlg.m_strFileName = strFile;
dlg.m_strSize = result.strFileSize;
dlg.m_strTime = result.strFileTime;
dlg.m_strFileDesc = result.strFileDesc;
dlg.m_strPos = result.strDir;
dlg.m_strFileType = result.strTypeName;
dlg.m_strFileTypeDesc = result.strTypeDesc;
dlg.DoModal();
}
// ((CMainFrame*)AfxGetMainWnd())->m_showView->ShowFileContext(strTemp.GetBuffer(0));
}
}
return true;
}
void CDirFileView::OpenFile()
{
CTreeCtrl & myTree = this->GetTreeCtrl();
HTREEITEM htiNext = myTree.GetSelectedItem();
HTREEITEM hRoot;
if (htiNext != NULL)
{
if ((hRoot = myTree.GetParentItem(htiNext)) == NULL) // 如果是文件类型,则展开
{
myTree.Expand(htiNext,TVE_EXPAND | TVE_COLLAPSERESET );
}
else // 在视图文件中打开文件
{
CString strTemp = myTree.GetItemText(htiNext);
((CMainFrame*)AfxGetMainWnd())->m_showView->ShowFileContext(strTemp.GetBuffer(0));
}
}
}
// ShowDocFilesView.cpp : implementation of the CShowDocFilesView class
//
#include "stdafx.h"
#include "DocFiles.h"
#include "DocFilesDoc.h"
#include "ShowDocFilesView.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CShowDocFilesView
IMPLEMENT_DYNCREATE(CShowDocFilesView, CFormView)
BEGIN_MESSAGE_MAP(CShowDocFilesView, CFormView)
//{{AFX_MSG_MAP(CShowDocFilesView)
ON_WM_SIZE()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CShowDocFilesView construction/destruction
CShowDocFilesView::CShowDocFilesView()
: CFormView(CShowDocFilesView::IDD)
{
//{{AFX_DATA_INIT(CShowDocFilesView)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// TODO: add construction code here
}
CShowDocFilesView::~CShowDocFilesView()
{
}
void CShowDocFilesView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CShowDocFilesView)
DDX_Control(pDX, IDC_EXPLORER_BROWER, m_ctrlShowContext);
//}}AFX_DATA_MAP
}
BOOL CShowDocFilesView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CFormView::PreCreateWindow(cs);
}
void CShowDocFilesView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
((CMainFrame *)AfxGetMainWnd())->m_showView = this;
}
/////////////////////////////////////////////////////////////////////////////
// CShowDocFilesView printing
BOOL CShowDocFilesView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CShowDocFilesView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CShowDocFilesView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
void CShowDocFilesView::OnPrint(CDC* pDC, CPrintInfo* /*pInfo*/)
{
// TODO: add customized printing code here
}
/////////////////////////////////////////////////////////////////////////////
// CShowDocFilesView diagnostics
#ifdef _DEBUG
void CShowDocFilesView::AssertValid() const
{
CFormView::AssertValid();
}
void CShowDocFilesView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
CDocFilesDoc* CShowDocFilesView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDocFilesDoc)));
return (CDocFilesDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CShowDocFilesView message handlers
void CShowDocFilesView::OnSize(UINT nType, int cx, int cy)
{
CFormView::OnSize(nType, cx, cy);
if (::IsWindow(m_ctrlShowContext))
{
CRect rect(0,0,cx,cy);
m_ctrlShowContext.MoveWindow(&rect);// 调解窗口大小
}
// TODO: Add your message handler code here
}
bool CShowDocFilesView::ShowFileContext(char *lpszFileName)
{
//m_ctrlShowContext.Navigate("F:\\books\\c++\\C++-CLI Standard.pdf",NULL,NULL,NULL,NULL);
m_ctrlShowContext.Navigate(lpszFileName,NULL,NULL,NULL,NULL);
UpdateData(false);
return true;
}
参 考 文 献
1、《Visual C++新起点》 康博创作室编著 机械工业出版社
2、《面向对象的方法学与C++》王斌君等编著 西北大学出版社
3、《中文版Access 2000入门与提高》,姜晓铭 杜吉祥主编
4、《Visual C++ MFC 编程实例》,斯文克 Swanke
5、《SQL查询语言及应用》王冠编著 科学出版社
7、《数据库系统原理》 王珊 电子工业出版社
8、《数据库技术及其应用》 王鹏,董群编著 人民邮电出版社
9、《Access 2000中文版实用培训教程》 白松涛编著
10、《分布式数据库技术》 贾焰 国防工业出版社发行部
11、《Visual C++ 6.0 技术内幕》(美)Eugene Olafsen kenn Scribner K.David white
12、《MFC技术内幕》 [美] Al Williams
13、《VC++技术内幕》 潘爱民、王国印译 清华大学出版社
14、《Visual C++ 程序设计基础》 戴锋编著 清华大学出版社
15、《Visual C++界面编程技术》 周鸣扬 北京希望电子出版社
16、《Visual C++最新编程实践与技巧》 李明柱单 肃 赵先启 编著 北京航空航天大学出版社
17、《分布式数据库系统及应》 邵佩英编著 科学出版社