学生成绩管理系统详细操作过程.docx
《学生成绩管理系统详细操作过程.docx》由会员分享,可在线阅读,更多相关《学生成绩管理系统详细操作过程.docx(36页珍藏版)》请在冰豆网上搜索。
学生成绩管理系统详细操作过程
学生成绩管理系统
我将把我的实现步骤完整的写出来,我是在VC6.0版本下用MFC实现的。
我创建的基于单文档的应用程序,过程不介绍,大家都会。
下面的是我系统菜单:
思路:
刚进入系统时,只有“登录”菜单可用,其他三个菜单项都是灰色不可用的。
当用户点“进入系统”菜单项时,用户输入用户名、密码和用户类型,系统将根据相应的用户权限使相应的菜单可用,并且“进入系统”菜单项变为不可用。
如:
如果用户类型是学生,那么只有学生权限菜单可用,而“教师权限”和“管理员权限”都不可用,同时“进入系统”变为不可用。
“学生权限”下只有“查询成绩”,因为学生只可以查询自己相应的成绩;“教师权限”下有“查询学生成绩”和“增改删学生成绩”两个菜单项,因为教师除了可以查询学生成绩还可以增加、修改和删除学生成绩;“管理员权限”下有“管理学生”和“管理教师”两个菜单项。
整体设计:
因为我们要设置系统菜单的状态,所以必须在CMainFrame中添加相应的函数和代码,具体步骤如下:
【步骤1】由于系统要使用ODBC类操作数据库,所以需要在stdafx.h中加入代码:
#include<afxdb.h>
【步骤2】在CMainFrame中的OnCreat()中添加代码如下,实现菜单的初始化工作,当用户没进入系统之前,只有“登陆”菜单下的“进入系统”菜单项可用,而“退出系统”和其他3个权限菜单都不可用,即都是灰色的。
intCMainFrame:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
{
//使“退出系统”和其他3个权限菜单都不可用,即都是灰色的
GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION|MF_DISABLED| MF_GRAYED);ﻩﻩ
GetMenu()->EnableMenuItem(1,MF_BYPOSITION| MF_DISABLED|MF_GRAYED);
GetMenu()->EnableMenuItem(2,MF_BYPOSITION | MF_DISABLED |MF_GRAYED);
GetMenu()-> EnableMenuItem(3,MF_BYPOSITION | MF_DISABLED| MF_GRAYED);
}
【步骤3】在CMainFrame中添加自己定义的函数void SetMenuSta(inttype),此函数在登陆对话框的OnOK()中被调用,即当用户进入系统后使“进入系统”菜单项不可用,并根据用户类型使相应菜单可用。
当类型为1时(学生),使“学生权限”菜单可用;当类型为2时(教师),使“教师权限”菜单可用;当类型为3时,使“管理员”菜单可用。
voidCMainFrame:
:
SetMenuSta(inttype)
{
AfxGetMainWnd()->GetMenu()->GetSubMenu(0)->EnableMenuItem(0,MF_BYPOSITION|MF_DISABLED| MF_GRAYED);
if(type==1)
ﻩ{
AfxGetMainWnd()->GetMenu()->EnableMenuItem(1,MF_BYPOSI TION| MF_ENABLED);
//在上面的OnCreate中可以直接通过GetMenu()对菜单操作,
ﻩﻩ //但这里却必须先通过AfxGetMainWnd()获得主窗体指针,
ﻩ //浪费了我一晚上时间,虽然解决了,但还不知道为什么。
ﻩ }
if(type==2)
{
AfxGetMainWnd()->GetMenu()->EnableMenuItem(2,MF_BYPOSITION | MF_ENABLED);
ﻩ}
if(type==3)
{
AfxGetMainWnd()->GetMenu()->EnableMenuItem(3,MF_BYPOSITION|MF_ENABLED);
ﻩ}
}
【步骤4】通过上面两步并不能按我们的想法实现菜单变灰的操作,运行系统各菜单都是可用的,我们必须在CMainFrame的构造函数中添加下面一句代码:
m_bAutoMenuEnable=FALSE;
m_bAutoMenuEnable必须放在ﻩCMainFrame()里初始化,不可用放在登陆对话框的OnOK()函数中,要不其他三个菜单可用变灰,但“进入系统”菜单项却总是不能变灰。
数据库设计:
根据以上思路,我们使用SQL数据库建立一个“学生成绩管理系统”,其下有4张表,分别为用户表USERS、学生成绩表COURSE_SCORE、学生信息表STUDENT_INFO和教师信息表TEACHER_INFO。
表1用户表USERS
字段名 类型长度 说明
USER_ID char 20 用户名
USER_PASSWORD char 20 密码
USER_TYPE int 41为学生,2为教师,3为管理员
表2学生成绩表COURSE_SCORE
字段名 类型长度 说明
STU_ID char 10 学生ID,系统中学生的唯一标识
COURSE_ID char 10 课程号,系统中课程的唯一标识
COURSE_NAME char 10 课程名
SCORE int 4 课程分数
表3 学生信息表STUDENT_INFO
字段名 类型长度说明
STU_ID char 10 学生ID,系统中学生的唯一标识
STU_NAME char 10 学生姓名
ENROLLMENT_TIME datetime8 入学时间
DEPARTMENT char20 所在学院
MAJOR char 20 所在专业
SEX int 4 性别:
0表示男,1表示女
BIRTHDAY datetime8 生日
HOMETOWN varchar 50 籍贯
ADDRESS varchar 50 现在住址
PHONE char 20 个人电话号码
RACE char 10 民族
PARTY int 4 政治面貌:
0表示党员,1表示预备党员,2表示团员,3表示其他
DIRECTION varchar50 其他信息
具体实现步骤:
(一)登陆模块设计
1、当刚进入系统时候,用户点击“进入系统”菜单项后系统界面如下:
按上面的登陆对话框摆放好控件,其中各个控件ID及对应变量如下图所示:
从上图中也可以看出,我们为该登陆对话框建立了个新类:
CLoginDlg,它的具体创建过程就不介绍了。
2、因为登陆对话框要使用SQL数据库中的USERS表,所以需要在程序中添加类CLoginSet,步骤如下:
【步骤1】在项目名“学生成绩管理系统”上单击鼠标右键,在弹出的NewClass对话框中的Name文本框中输入CLoginSet,在Baseclass下拉文本框中选择CRecordset。
【步骤2】单击OK按钮,弹出DatabaseOption对话框,在ODBC下拉文本框中选择“学生成绩管理系统”数据库,单击OK按钮,弹出SelectDatabaseTables对话框,选择dbo.USERS选项,单击OK按钮。
这样就建立了一个CRecordset的对象,就可以对数据库中的USERS表进行操作了。
3、在LoginDlg.cpp中引入头文件LoginSet.h,将CRecordSet对象CLoginSet引入登陆对话框:
#include“LoginSet.h”
4、声明全局变量。
在学生成绩管理系统.cpp文件中添加如下代码:
//CDatabase型变量,用于连接数据库
CDatabasem_database;
//学生登陆后在系统中的唯一ID值
CStringm_ID;
在LoginDlg.cpp添加如下语句,使用已经声明过的全局变量(记得在以后的每个模块中都要添加):
externCDatabasem_database;
externCString m_ID;
5、为登陆对话框的“确定”按钮添加消息代码,如下:
void CLoginDlg:
:
OnOK()
{
ﻩBOOLbLogin=FALSE;
ﻩCLoginSet*m_recordset=new CLoginSet(&m_database);
CStringstrSQL;
ﻩUpdateData(TRUE);
ﻩif(m_usetype.Compare("学生")==0)
ﻩtype=1;
else
ﻩif(m_usetype.Compare("教师")==0)
ﻩﻩﻩtype=2;
else
if(m_usetype.Compare("管理员")==0)
ﻩtype=3;
strSQL.Format("select *fromUSERS where USER_ID='%s'ANDUSER_PASSWORD='%s'ANDUSER_TYPE='%d'",
ﻩm_useID,m_usepassword,type);
ﻩm_recordset->Open(AFX_DB_USE_DEFAULT_TYPE,strSQL);
ﻩif(m_recordset->GetRecordCount()==0)
ﻩ{
ﻩif(count<3)
ﻩﻩ{
ﻩﻩMessageBox("用户名或密码不正确!
");
ﻩm_useID="";
ﻩm_usepassword="";
UpdateData(FALSE);//没有这条语句就不能实现使账号和密码文本框为空,很多人会忘记写这条语句。
count++;
ﻩ}
else
ﻩ{
ﻩﻩMessageBox("错误次数达三次以上,本窗口即将关闭!
");
ﻩﻩEndDialog(IDCANCEL);
ﻩ}
ﻩ}
ﻩelse
ﻩ{
m_recordset->GetFieldValue("USER_ID",m_ID);
ﻩﻩbLogin=TRUE;
ﻩ}
if(bLogin)
ﻩ{
ﻩMessageBox("欢迎进入学生成绩管理系统!
");
EndDialog(IDOK);
ﻩﻩCMainFrame *mainfrm=newCMainFrame();
mainfrm->SetMenuSta(type);
}
ﻩelse
ﻩﻩm_database.Close();
//CDialog:
:
OnOK();
}
6、为登陆菜单下的“进入系统”添加响应函数,此函数是在CMainFrame类中添加的,代码如下:
voidCMainFrame:
:
OnLogin()
{
//TODO:
Addyourcommandhandler codehere
ﻩCLoginDlglogin;
login.DoModal();
}
(二)学生成绩查询模块设计
1、 如果用户类型是1,即学生时,用户可以查询自己的成绩。
在其中用户可以根据课程号或者课程名查询自己的成绩。
按上面的学生成绩查询对话框摆放好控件,其中各个控件ID及对应变量如下图所示:
从上图中也可以看出,我们为该学生成绩查询对话框建立了个新类:
CStuCheckScoreDlg,它的具体创建过程就不介绍了。
2、因为学生成绩查询对话框要使用SQL数据库中的COURSE_SCORE表,所以需要在程序中添加类CCourseScoreSet,步骤如下:
【步骤1】在项目名“学生成绩管理系统”上单击鼠标右键,在弹出的NewClass对话框中的Name文本框中输入CCourseScoreSet,在Baseclass下拉文本框中选择CRecordset。
【步骤2】单击OK按钮,弹出Database Option对话框,在ODBC下拉文本框中选择“学生成绩管理系统”数据库,单击OK按钮,弹出SelectDatabaseTables对话框,选择dbo.COURSE_SCORE选项,单击OK按钮。
这样就建立了一个CRecordset的对象,就可以对数据库中的COURSE_SCORE表进行操作了。
3、在StuCheckScoreDlg.cpp中引入头文件CourseScoreSet.h,将CRecordSet对象CCourseScoreSet引入登陆对话框:
#include “CourseScoreSet.h”
4、在StuCheckScoreDlg.cpp添加如下语句,使用已经声明过的全局变量(记得在以后的每个模块中都要添加):
externCDatabasem_database;
externCString m_ID;
5、为学生成绩查询模块的“查询”按钮添加响应事件:
void CStuCheckScoreDlg:
:
OnCheckButton()
{
CStringstrSQL;
CDBVariantvarValue;
ﻩUpdateData(TRUE);
ﻩif(m_keyword.Compare("课程号")==0)
strSQL.Format("select *from COURSE_SCOREwhereCOURSE_ID='%s'",m_cost);
else
strSQL.Format("select *fromCOURSE_SCOREwhereCOURSE_NAME='%s'",m_cost);
ﻩCCourseScoreSet *m_recordset=new CCourseScoreSet(&m_database);
ﻩm_recordset->Open(AFX_DB_USE_DEFAULT_TYPE,strSQL);
if(m_recordset->GetRecordCount()==0)
ﻩ{
ﻩMessageBox("对不起,没有您所需要的结果,请核对后重新输入!
");
}
else
{
ﻩﻩinttemp=0;
ﻩﻩm_stuID=m_recordset->m_STU_ID;
ﻩm_courseID=m_recordset->m_COURSE_ID;
m_coursename=m_recordset->m_COURSE_NAME;
ﻩm_score=m_recordset->m_SCORE;
ﻩ}
m_recordset->Close();
ﻩUpdateData(FALSE);ﻩ
}
注意:
在上面我们对对话框中各个文本框对应的变量进行赋值时,并不是使用 m_recordset->GetFieldValue(3,varValue);
ﻩ m_coursename=varValue.m_pstring->GetBuffer(1);
不用这么麻烦的写法,直接用m_recordset中的变量就行了,m_recordset中的变量对应这数据库表中的各个字段,且和表中字段类型都一致。
(三)教师操作学生成绩信息模块设计
1、如果用户类型是2,即教师时,用户可以查询学生的成绩,还可以对学生成绩进行增、改、删操作。
查询学生成绩和上个模块差不多,就不做了。
而对学生成绩的增、改、删操作就是通过这个模板实现的。
界面如下:
在其中的列表控件中显示COURSE_SCORE中所有的信息,并且当用户点击其中一行时,可以在上面的文本框中进行显示。
按上面的对话框摆放好控件,其中各个控件ID及对应变量如下图所示:
从上图中也可以看出,我们为该教师操作学生成绩对话框建立了个新类:
COperateScore,它的具体创建过程就不介绍了。
2、因为教师操作学生成绩对话框也要使用SQL数据库中的COURSE_SCORE表,所以需要在OperateScore.cpp中引入在前面创建的COURSE_SCORE表所对应的记录集对象的头文件CourseScoreSet.h,将CRecordSet对象CCourseScoreSet引入登陆对话框:
#include“CourseScoreSet.h”
3、 在OperateScore.cpp添加如下语句,使用已经声明过的全局变量(记得在以后的每个模块中都要添加):
externCDatabasem_database;
extern CString m_ID;
4、因为该对话框中含有列表控件,我们需要对其进行初始化,让列表控件一开始就显示COURSE_SCORE表中的所有记录,并且把列表控件中的第一条记录显示在上面的文本框中。
【步骤1】右键点击COperateScore,在弹出的菜单中选择“Addwindows messagehandle”项,然后在弹出的对话框的“新建windows消息/事件”中选择“WM_INITDIALOG”,然后点击“AddHandle”按钮,最后点击“EditExisting”
按钮,编写代码如下:
BOOLCOperateScore:
:
OnInitDialog()
{
ﻩCDialog:
:
OnInitDialog();
m_listscore.InsertColumn(0,"学号");
m_listscore.InsertColumn(1,"课程号");
m_listscore.InsertColumn(2,"课程名");
m_listscore.InsertColumn(3,"成绩");
RECT rect;
m_listscore.GetWindowRect(&rect);
intwidth=rect.right-rect.left;
ﻩm_listscore.SetColumnWidth(0,width/4);
ﻩm_listscore.SetColumnWidth(1,width/4);
ﻩm_listscore.SetColumnWidth(2,width/4);
ﻩm_listscore.SetColumnWidth(3,width/4);
m_listscore.SetExtendedStyle(LVS_EX_FULLROWSELECT);
ﻩinitial();
//TODO:
Addextrainitializationhere
ﻩ
ﻩreturnTRUE; //return TRUEunlessyousetthefocustoacontrol
ﻩ //EXCEPTION:
OCX PropertyPagesshouldreturnFALSE
}
【步骤2】在上面的OnInitDialog()函数中我们设置了列表控件的表头和每列的间距,并在最后调用了initial()函数。
initial()是我自定义的一个函数,用来将COURSE_SCORE表中的数据全部在该列表控件中显示出来。
该函数是自定义函数,添加过程比较简单,不介绍。
代码如下:
voidCOperateScore:
:
initial()
{
m_listscore.DeleteAllItems();
CDBVariantvarValue[20][4];
CCourseScoreSetm_recordset;
intj=m_recordset.GetDatebase(varValue);
intk;
ﻩint i=0;
charbuf[20];
ﻩfor(k=0;k<j;k++)
ﻩ{
////用来处理数据表中的字符型字段
ﻩm_listscore.InsertItem(i,varValue[k][0].m_pstring->GetBuffer
(1));
ﻩm_listscore.SetItemText(i,1,varValue[k][1].m_pstring->GetBuffer(1));
m_listscore.SetItemText(i,2,varValue[k][2].m_pstring->GetBuffer
(1));
ﻩﻩ//用来处理数据表中的整型字段
sprintf(buf,"%d",varValue[k][3].m_iVal);
ﻩﻩm_listscore.SetItemText(i,3,buf);
ﻩ}
i=0;
settext(0);
}
varValue[20][4]是CDBVariant型的,该类型的变量可以用来存储数据表中任意类型的字段,所在在数据库操作时用该变量比较方便。
变量j表示COURSE_SCORE数据表中的行数,通过for循环把该数据表中的所有记录全部显示出来。
数据表中的前3个字段我都是用varValue[k][0].m_pstring->GetBuffer
(1)来显示在列表控件中,是因为数据表中前3个字段都是字符型的,而最后一个字段是用来显示分数的,该字段在数据表中我定义为了整型,所有用sprintf(buf,"%d",varValue[k][3].m_iVal);m_listscore.SetItemText(i,3,buf);来显示。
【步骤3】在上面的initial()函数中我调用了GetDatebase(varValue)函数,该函数返回COURSE_SCORE数据表中的记录条数,我们将其赋给了j。
并且该函数把COURSE_SCORE表中所有记录都存储在二维数组varValue中。
在前面两个模块中我对数据库操作都是直接在该模块中操作的,但现在我要换种方法。
我把对数据库的操作封装在了记录集类CCourseScoreSet中,这样避免混乱。
在记录集类CCourseScoreSet中添加GetDatebase(varValue)函数,注意:
因为我们要在类COperateScore调用该函数,所有我们必须要把该函数定义为public型。
其代码如下:
intCCourseScoreSet:
:
GetDatebase(CDBVariantvarValue[][4])
{
CCourseScoreSetm_recordset(&m_database);
CStringstrSQL;
ﻩstrSQL.Format("select*fromCOURSE_SCORE");
ﻩm_recordset.Open(AFX_DB_USE_DEFAULT_TYPE,strSQL);
if(m_recordset.GetRecordCount()!
=0)
m_recordset.MoveFirst();
ﻩintj=0;
ﻩwhile(!
m_recordse