0. 预备步骤
到这一步之前,必须已经建立好数据库文件(我们的系统中是一个.mdb文件),并且数据库中的所有表格都已经有测试数据。
1. 调整数据库中的数据
为了同学们的报表有区别,每位同学应该有针对性的修改自己的数据。做同学表的单号同学,只需打印出一名同学所选的所有课程的有关信息即可,要求至少该同学至少选修3门以上的课程,给出期末成绩,并计算出绩点分(或平均分)。做教师表的双号同学,只需打印出一名教师所讲的一门课程的成绩信息即可,要求至少有5名以上的同学修读该课程,给出期末成绩,并给出成绩统计。
2. ODBC(Open DataBbase Connection)与CRecordSet类
这是MFC数据编程的一个重要步骤。ODBC是Windows的一个系统程序,而VC,和PowerDesigner一样,都是Windows的一个应用程序。VC程序要访问另一个程序中的数据,必须通过Windows操作系统提供的某种方法与同时运行在Windows操作系统下Access数据库进行通信。最简单的通信机制就是ODBC。
MFC中封装了ODBC访问方法的对象是CRecordSet,该对象代表了对数据库进行一次访问所得纪录集合的一个数据结构。由于VC是面向过程的第三代编程语言,而访问数据库的SQL语言是面对集合的编程语言。CRecordSet这个类提供了必要的方法和技术进行这两类结构的匹配。
CRecordSet类是一个非常重要的类,详细的信息需同学们参照MSDN或网络自己学习。这里仅简要介绍我们所必须的一些方法。Open方法建立与数据库默认连接,并进行默认查询。Close方法断开与数据库的连接。GetRecordCount()方法返回本次查询结果中纪录集的个数。由于在一个纪录集中通常会有多条纪录,CRecordSet提供了一个类似于指针的游标(Cursor)结构,它就像一个指针一样可以在纪录集中前后移动,以便于我们访问纪录集中的全部数据。记住,VC只能访问当前游标所指的记录。因此,如果要访问纪录集中其它的记录,必须通过CRecordSet类提供的方法移动游标。这些方法包括Move(), MoveFirst(), MoveLast(), MoveNext(), MovePrevious()等。开始时游标指向第一条记录之前,此时IsBOF()函数返回True。当游标移动到最后一条记录之后,此时IsEOF()函数返回True。
3. 建立ODBC(Open DataBbase Connection)连接
在控制面板中运行ODBC程序,建立一个系统DSN,注意我们给起的名字,同时制定一个数据库(这个数据库最好就是PowerDesigner自动生成的那个数据库)。
4. 生成MFC程序
用VC的AppWizard新建一个单文档的MFC程序(自动生成的第一步选择’单文档’Single Document,其它保持默认),并通过‘资源管理器’编辑菜单界面添加一项程序访问入口,如‘数据库’→‘浏览’,定义其ID为IDC_MENU_DB_BROWSE。保持该项目为选中状态,按Ctrl+W激活ClassWizard(类向导),在文档类(C____Doc)中为该命令添加响应函数(即在这里定义这个命令应该做的事情),这里就是我们需要编程的地方。一定要注意,在添加响应函数时,默认的类是框架类(C____Frame)而不是文档类,这里一定要注意修改。
5. 添加CRecordSet类的派生类
通过ClassWizard添加数据库访问的CRecordSet类的派生类。现在该访问数据库的时候了,首先按Ctrl+W调出ClassWizard,按右上角第一个按钮‘Add Class…’右侧的小三角号,在弹出的菜单中选择‘New’,系统弹出’New Class’对话框,在’Base class’下拉列表中选择CRecordSet类,这就是我们要生成类的父类。对‘Name’中输入我们新建类的名称,一般用C开头,Set结尾,如访问课程表(Course),就叫做CCourseSet,访问学生就叫做CStudentSet。我们以学生表为例,因此我们的类命名为CStudentSet。Click OK. 下面就到了关键的一步’Database Option’对话框,指定该类要访问的数据库及某个特定表。保持默认,在ODBC后面的下拉列表狂中找到我们在第3步建立的系统DSN,Click OK.【注意:如果此时的下拉列表中没有你要的系统DSN名称,必须重新运行第3步新建一个】。在系统随后弹出的’Select Database Tables’对话框中选择一个表【此时数据库中所有对象都应该在这里,有Table, 有Query, if any.】,这里是Student,Click OK.一路点击OK,新类生成完毕并自动添加到我们的工程(Project)中。如果系统弹出提示类没有添加到工程的错误提示,一般是由于我们的路径中有空格或汉字,需要修改整个工程的路径后再来一遍。
6. 完成浏览数据库的函数
下面是完成第4步添加的‘浏览’‘数据库’函数的时候了。首先在文档类(C____Doc)中添加一个类型为CStudentSet的新数据成员,命名为m_cStudentSet. 当然为了编译通过,还需要在该类的定义前添加#include “StudentSet.h语句嵌入该类的声明。在编译之前还要在StdAfx.h(预编译头文件)文件中添加#include “AfxDb.h”语句。最后在文档类(C____Doc)对应的C语言文件中(不是头文件),找到浏览数据库的函数,把类似于下面的代码粘贴到函数中就可以实现浏览数据库Student表全部记录的功能。
AfxMessageBox("Connecting to the database");
if(FALSE==m_cStudentSet.Open())
AfxMessageBox("Connect Failure");
else
AfxMessageBox("Connected.");
if(m_cStudentSet.GetRecordCount()>0) //There is any records in the table
{
m_cStudentSet.MoveFirst();
CString strRecord;
int iNumber = 1;
//Browse each record
while(!m_cStudentSet.IsEOF())
{
//Construction the prompt string
strRecord.Format("The %2d record: ",iNumber);
strRecord += m_cStudentSet.m_SID;
strRecord += ", \\nName: ";
strRecord += m_cStudentSet.m_SName;
strRecord += "\\nClass: ";
strRecord += m_cStudentSet.m_Grade;
AfxMessageBox(strRecord);
m_cStudentSet.MoveNext();
iNumber++;
}
strRecord.Format("Browse Complete. Totally %d records.",iNumber-1);
AfxMessageBox(strRecord);
}
else
AfxMessageBox("There is no records in the table");
//Close and disconnect the databese
AfxMessageBox("disconnect the database.");
m_cStudentSet.Close();
7.在视类中显示信息和表格
这是最后一个重要步骤,需要在视类中显示程序的有关数据。文档-视(Document-View)是MFC推出的重要体系架构,其核心思想是所有对数据的操作都放到文档类(Document)中进行,而所有显示的操作都放到视类(View)进行。显然,显示离不开数据,MFC提供了在视类访问文档类数据的办法——到文档类的指针。有了这个指针,文档类的所有数据、函数都能访问到。
在视类中的显示函数是OnDraw,自动生成的这个函数内容如下:
void CTestDatabaseView::OnDraw(CDC* pDC)
{
CTestDatabaseDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
OnDraw的工作原理是Windows消息队列中有WM_PAINT消息时自动调用,因此该函数就由Windows操作系统在它认为需要刷新显示的时候自动调用,我们可以理解为周期性的自动执行即可。
函数中的pDoc就是我们说的指向文档类的指针,例如pDoc-> m_cStudentSet. m_Grade就能获得文档类中m_cStudentSet当前游标所指记录的Grade字段的值。当然我们的程序在浏览过后关闭了到数据库的链接,当前游标所指记录没有定义,值一般来说自然就不正确了。因此为了在视类中显示我们所关心的数据,还要想办法把数据库的数据存储到VC程序的数组等变量中,程序不结束,这些变量的值就有意义。
显示的核心语句是TextOut函数。TextOut的用法说明如下:
//Writes a character string at the specified location using the currently selected font.
BOOL TextOut( int x, int y, const CString& str );
Return Value: Nonzero if the function is successful; otherwise 0.
Parameters:
x, Specifies the logical x-coordinate of the starting point of the text.
y, Specifies the logical y-coordinate of the starting point of the text.
str, A CString object that contains the characters to be drawn.
例如:下面的语句可以显示的效果类似为:
pDC-> TextOut(50,10,”Course Information”);
pDC-> TextOut(10,50,”--------------------------------------------------------------------------”);
pDC-> TextOut(10,90,”Course ID: EL1206 Course Name : SDM Credits : 4”);
pDC-> TextOut(10,130,”-------------------------------------------------------------------------”);
pDC-> TextOut(10,170,”Course ID: 7050504 Course Name : Math Credits : 6”);
pDC-> TextOut(10,210,”--------------------------------------------------------------------------”);
执行后的效果为:
Course Information
--------------------------------------------------------------------------
Course ID: EL1206 Course Name : SDM Credits : 4
--------------------------------------------------------------------------
Course ID: 7050504 Course Name : Math Credits : 6
--------------------------------------------------------------------------
这就是我需要大家做出来的最后表格的最低要求,当然格式越像越好,字体越精美越好。大家用类似的语句,将具体的课号、名称、学分等换上存储在文档类中的数据就能显示你所要的结果了。要注意,文档类中的数据也必须事先从数据库的相应表中先拿出来。下载本文