基于VC++的研究生IMS对话框初步设计
2010-06-05张占阳
张占阳
(长安大学 地测学院 地理信息系统系,陕西 西安 710054)
传统的信息管理系统涉及的内容广泛,但社会对其发展和完善有了极大增加,因而规范管理、提高工作效率已变得尤为重要[1-3]。一般情况下,在系统总体设计和系统编码实现的过程中就已经设定了属性段或值域,从而使得外部信息或数据录入时只能n:n对号入座,而采集或收集的其他附加信息就有可能被忽略或删掉,这一部分无用信息由于无法录入到信息管理系统的数据库中而白白浪费掉。当然,一般的信息管理系统都给出了指定的字段,所以在输入数据时只需要按照指定的字段输入内容即可,只有当需要录入新的数据信息时才需要通过更新数据库来添加新的属性段或字段,但增加新字段使系统或数据库更新,会带来大量的人力或资金的消费。因此,这里针对研究生管理系统(IMS)设计了一种较为合理、更加完善的人机对话框来实现在录入基本信息或所需信息的同时能够实现附加类或新增类信息的录入。
1 研究生信息对话框建立
基于VC++建立一个 “隐藏工具栏”、“初始化状态栏”的单文档研究生IMS(信息管理系统)MFC[4]工程,该工程的具体目的是实现研究生基本信息、专业信息、选课信息及其对应新增附加信息的输入和录入。
1.1 研究生基本信息对话框
在MFC工程类中建立基于对话框类的研究生基本信息类(CBaseXinxi),并在该类中建立基本信息变量姓名、性别、民族、籍贯(省、市)、生日、血型、身高以及自我介绍等,其中姓名、民族、生日、身高和自我介绍属于编辑框类变量,性别属于单选框类变量,籍贯中的省及血型属于组合框类变量,市属于列表框类变量。
通过对研究生基本信息建立类向导导入初始化函数WM_InitDialog(),并在该函数中对各变量进行初始化,使性别变量默认为男性(即SetCheck(TRUE)),设定组合框变量“省”当前选择项目为第一个项目(即 SetCurSel(0)),再对列表框变量“市”通过AddString(项目名)添加第一个项目并将其作为默认选中项目,设定血型当前默认血型类型 (如O型)。建立基于组合框类“省”的响应函数WM_SelChange(),实现对省级以下各城市的不同选择。这样,基本信息对话框建立完成。但需要在工程Doc类中引入一个CBaseXinxi类的对象或指针,使得在View类菜单响应函数“输入研究生基本信息函数”中实现对该类对象或指针的调用并返回对话框中的基本信息,从而为后期的数据录入、数据处理、数据应用以及分析等奠定基础,图1为研究生基本信息的录入,研究生基本信息的显示则如图2所示。
图1 研究生基本信息输入示例Fig.1 Inputting example of graduate basic information
图2 研究生基本信息显示示例Fig.2 Displaying example of graduate basic information
1.2 研究生专业信息和选课信息对话框
一般情况下,当信息系统建立之后,只需按系统中给出的基本信息字段来采集学生对应的基本信息,如本示例研究生基本信息对话框中只需按照姓名、性别、民族、籍贯、生日、身高、血型和自我介绍来采集或录入各班级学生的数据作为各个记录,并将这些数据存入到指定库中。同理,研究生专业信息对话框类(CprofessioanXinxi)和研究生选课信息对话框类(CxuanKeXinxi)的建立思想和基本信息对话框大同小异,内含字段:姓名、学号、学院、专业、电话、导师等,数据录入和显示与前者思路类似,这里不再详细介绍。图3、图4分别为研究生专业信息对话框和选课信息录入对话框。
2 新增信息或附加信息录入研究
2.1 问题探讨
图3 研究生专业信息对话框Fig.3 Dialog box of graduate professional information
图4 研究生选课信息对话框Fig.4 Dialog box of graduate elective course information
对于系统对话框中给定的字段,只需录入指定的记录即可。但有时根据用户需求,需要增添许多新信息,相应的系统就必须增加许多新的功能模块来实现对新增数据的各种处理和应用,这就要求必须对系统和对应的数据库进行更新,而更新和建库费用又是巨大的,这就给系统库的更新和维护人员带来了很多新问题。因此提出了一种基于对话框的附加信息录入方法,在录入新增数据的同时既能指定字段或属性域,又能添加对应的各个记录数据。
2.2 新增或附加信息录入
对于新增数据,可以采用建立对话框的形式来解决附加数据类型和数据变量的转换和输入。附加信息录入步骤可大致归结如下:
1)在MFC工程中其他类不变的情况下,建立其派生类附加信息类 (CFujiaXinxin),同时规定其公有继承CDialog类;2)在附加信息类中增加字符串Cstring类型的指针或变量,其名称为字段或属性域1,同时增加一个CString类型的记录1变量,使新增字段和新增记录相对应;3)在CFujiaXinxin类中添加若干CString类型变量或指针,变量或指针名为字段或属性域 i(1<i<n,n为新增信息类数量);因为一般情况下一个字段对应一个小的记录数据,所以也需要增加若干CString类型的记录i变量 (1<i<n,n为新增信息类数据);4)对附加信息类进行初始化,使其中的CString型变量进行两两对应(即数据类型和数据变量的1:1对应);5)在各个信息类中引入CFujiaXinxin类的变量或指针,实现对附加信息类数据的调用;6)在各个信息类中增加按钮CButton类对象,并引入按钮相应函数[5];7)完善各个按钮响应函数,实现对应的数据处理、应用等,如通过附加信息类的变量或指针实现对附加信息的归类、存储、显示和其他数据分析与处理等功能;8)在工程类子类View类中调用各个信息对话框,再通过各个信息对话框调用附加信息类对话框,从而实现对不同附加信息类的分类对应存储和应用等。图5为附加信息的数据数录入,研究生附加选课信息显示则如图6所示。
图5 研究生附加选课信息录入示例Fig.5 Inputting example of graduate additional elective course information
图6 研究生附加选课信息显示示例Fig.6 Displaying example of graduate additional elective course information
3 附加信息类型转换
通过上述过程,可实现研究生基本信息、专业信息和选课信息的常规录入以及新增附加信息的基本录入。但需要注意的是,附加信息类中的变量类型都是CString型的,而录入的附加信息可能是 int型、folat型、Char型和 BSTR型或VARIANT型,也可能是几种类型的组合,这就需要讨论CString类型向不同类型的转换问题[6]。
CString是一种很有用的数据类型,它很大程度上简化了MFC中的许多操作,使得MFC在做字符串操作时方便很多。随着科技的飞速发展,CString型变量与其他类型变量之间的转换算法和方法也越来越完善,这里简单介绍VC++中CString型转换成int型、Char型和BSTR型的大致思路[7]。
3.1 CString型转化成int型
把CString类型的数据转化成整数类型最简单的方法就是使用标准的字符串到整数转换例程。虽然通常觉得使用_atoi()函数是一个好选择,但并非是唯一的正确选择。如果决定使用 Unicode字符,那就应该用_ttoi(),它在ANSI编码系统中被编译成_atoi(),而在 Unicode编码系统中编译成_wtoi()。 当然也可以考虑使用 _tcstoul()或者 _tcstol(),它们都能把字符串转换成任意进制的长整数(如二进制、八进制、十进制或十六进制),不同点在于前者转化后的数据是无符号的(unsigned),而后者相反。
3.2 CString型转化成Char*型
对于系统的某些属性段(如性别或地区编号等)可以设置成Char型的值域,而通过外部设备录入的信息为CString型数据,这时就需要考虑CString型向Char型转化的诸多问题。由于CString型转化为Char*型的方法比较普遍,这里主要介绍目前被广泛运用的3种转换方法。
3.2.1 强制类型转换为LPCTSTR
这是一种略微硬性的转换,有关“正确”的做法,人们在认识上还存在许多混乱,正确的使用方法有很多,但错误的使用方法可能与正确的使用方法一样多。首先要了解CString是一种很特殊的C++对象,里面包含了3个值:一个指向某个数据缓冲区的指针,一个是该缓冲中有效的字符记数,一个是缓冲区长度。有效字符数的大小可以是从0到该缓冲最大长度减1之间的任何数 (因为字符串结尾有一个NULL字符)。字符记数和缓冲区长度被巧妙隐藏。
除非做一些特殊的操作,否则不可能知道给CString对象分配的缓冲区的长度。这样,即使获得了该0缓冲的地址,也无法更改其中的内容,不能截短字符串,也绝对没有办法加长它的内容,否则第一时间就会看到溢出。LPCTSTR操作符(或者更明确地说就是 TCHAR*操作符)在 CString类中被重载了,该操作符的定义是返回缓冲区的地址。因此,如果需要一个指向CString的字符串指针的话,可以这样做:
这是由C语言的强制类型转化规则实现的,当需要强制类型转化时,C++规定允许这种选择。这种强制转化适合所有这种情况,任何带有LPCTSTR类型参数的函数都会强制执行这种转换。有一件事情是不能做的,那就是修改字符串。比如,尝试用“,”代替“.”,不要这样做,因为由于国际化问题,应该使用十进制转换的National Language Support特性。需注意的是,缓冲有一个计数,它是不可存取的(它位于CString地址之下的一个隐藏区域),如果改变这个串,缓冲中的字符计数不会反映所做的修改。此外,如果字符串长度恰好是该字符串物理限制的长度,那么扩展该字符串将改写缓冲以外的任何数据,那就是改写无权进行写操作的内存数据,也会毁坏不属于自己的内存,这也是应用程序真正的致命之处。
3.2.2 使用CString对象的GetBuffer方法
有时如果需要修改CString型变量中的内容,有一个特殊的方法可以使用,就是调用CString型变量的GetBuffer()函数,它的作用是返回一个可写的缓冲指针。如果只是打算修改字符或截短字符串,可以通过如下代码实现:
这是GetBuffer的第一种用法,也是最简单的一种,不用给它传递参数,它使用默认值0,意思是使用该字符串指针但不加长它。当调用ReleaseBuffer时,字符串的实际长度会被重新计算,然后被存入到CString对象中。必须强调一点,在GetBuffer()和 ReleaseBuffer()范围中,一定不要调用操作缓冲函数的CString型对象的任何方法。因为ReleaseBuffer()被调用之前,该CString型对象的完整性得不到保障。
需要注意的是,如果有一个常量串指针,这个串指针本身的值被存储在只读内存中,如果试图存储它,即使已经调用了GetBuffer(),并获得一个只读内存的指针,存入操作也会失败,并报告指针值存取错误。通常C程序员都有一个通病就是分配一个固定长度的缓冲,对它进行sprintf()操作,然后将它赋值给一个CString型的变量或指针。如下面示例:
采用此方法,即使字符串长度超过指定字符长度的时候,也不会破坏堆栈。
还有一个常见的错误就是:既然固定大小的内存不工作,那么就采用动态分配字节。但这种做法弊端更为明显。如下示例:
其实它可以能被简单地写成:
需要注意,sprintf()例子都不是Unicode就绪的,尽管可以使用tsprintf()以及用_T()来包围格式化字符串,但是基本思路不变,而且是在走弯路,也很容易出错。
3.2.3 利用控件接口
经常需要把一个CString型的值传递给一个控件,如CComboxCtrl、CTreeviewCtrl等。MFC提供了很多便利来重载这个操作,但在大多数情况下,使用“原始”形式的更新,因此需要将某个串指针存储到TVINSERTITEMSTRUCT结构的TVITEM成员中。如果打算获取存储在控件中的数据,则所需方法稍有不同,如对某个CTreeCtrl使用GetItem()方法想获取项目的文本。但知道这些文本的长度不会超过limit_length,可以这样写:
其实上面代码对所有类型的Set方法都适用,但并不需要都这么做,因为所有类型的Set方法(包括Insert方法)都不会改变字符串的内容。但当需要写CString型对象时,必须保证缓冲是可写的,这正是GetBuffer()所做的事。需注意:一旦调用了一次 GetBuffer()函数,那么在调用 ReleaseBuffer()之前不要对此CString型对象做任何操作。
3.3 CString型转化成BSTR型
当使用ActiveX控件编程时,经常需要将某个值表示成BSTR类型。BSTR是一种记数字符串,是Intel平台上的宽字符串(Unicode),而且可以包含嵌入的NULL字符。可以调用CString对象的AllocSysString方法将CString转化成 BSTR:
现在指针b指向的就是一个新分配的BSTR对象,该对象是CString的一个拷贝,其中包含结尾NULL字符,现在可以将它传递给任何需要BSTR的接口。通常情况下,BSTR由接收它的组件释放,如果需要自己释放 BSTR,可以调用此函数:SysFreeString(b)。
综上所述,在子类函数中对附加信息类进行访问,能在输入基本信息的同时又实现对新增信息的输入和分类以及各分类变量的录入和存储。
4 结束语
通过在需要扩增新信息的各个类中调用新增或附加信息类的对象即可实现对新增信息的逐一访问,同时为实现对新增数据的后期应用和处理分析等奠定了基础。而附加信息类对话框不仅能够对新录入的非同类信息进行分类存储,而且实现了录入数据类型与研究生信息管理系统(IMS)数据库所需数据类型之间的相互转换。从而在一定程度上解决了因系统或数据库更新而带来的时间冗长、资金庞大的问题。
[1]吴涵.基于VC++的研究生信息管理系统的设计与实现[J].计算机技术与发展,2006,16(12):184-186.WU Han.Design and implementation of graduate information management system based on VC++[J].Computer Technology and Development,2006,16(12):184-186.
[2]王佩红,刘慧婷.基于VB的学生成绩管理系统的设计与实现[J].计算机技术与发展,2007,17(12):169-172.WANG Pei-hong,LIU Hui-ting.Design and realization of student achievements management system based on VB[J].Computer Technology And Development,2007,17(12):169-172.
[3]刘成忠,王联国.学位与研究生管理信息系统设计[J].甘肃科技,2006,22(9):60-61,71.LIU Cheng-zhong,WANG Lian-guo.Design of the degree and graduate managementinformation system[J].Gansu Science and Technology,2006,22(9):60-61,71.
[4]李英.Visual C++编程与项目开发[M].上海:华东理工大学出版社,2008.
[5]汪旭冉.VC++6.0在对话框最小化与提示条设计中的应用分析[J].黑龙江科技信息,2008(23):71-71,50.WANG Xu-ran.Application and analysis of VC++6.0 in minimizing the dialog box and designing the article tips[J].Heilongjiang Technology Information,2008(23):71-71,50.
[6]王燕.面向对象的理论与C++实践[M].北京:清华大学出版社,1996.
[7]侯俊杰.深入浅出MFC[M].武汉:华中科技大学出版社,2001.