ps:因为课设完成的过程大家都不太一样,以下的代码仅供学习一下在MFC下各个控件的用法,有问题欢迎留言讨论。
二、实验内容
本次c++课设的学生成绩管理系统是面向学生和教师的。该系统有三种身份账号,其中学生账号可以在里面查询自己的成绩,而教师账号可以添加,删除和修改学生的成绩,而管理员账号可以添加,删除和修改学生的成绩外,还能可以添加,删除和修改登录使用的账号。
另外,用单文档设计的学生成绩分析图形绘制。并用该学生成绩管理系统调用该画图的exe文件,实现在该学生成绩管理系统中显示学生成绩的直方图和曲线图。
登录界面:
学生成绩管理界面:
(1)、设计一个学生类Student,包括数据成员:姓名、学号、五门课程(高等数学,离散数学,C++课设,大学英语,大学体育)的成绩。
(2)、创建一个基于对话框的MFC应用程序,程序窗口的标题上有你姓名、学号和应用程序名称。使用(1)的类,实现对学生信息和成绩的输入和管理。
(3)、创建一个单文档的MFC应用程序,读取(2)中保存的文件中的学生成绩,分别用直方图和折线方式显示所有学生某课程的成绩分布图。
(4)创建一个登录管理界面,学生可以用学生账号登录查看成绩,教师可以使用教师账号登录查看并添加,删除,修改学生的成绩。而管理员账号可以添加,删除和修改学生和老师的登录账号,老师和学生账号只能修改自身的登录密码。
(5)创建一个学生成绩管理主界面,上面有list控件之间将存储在文件的学生信息显示在主界面上,另外还有查找控件,组合控件进行排序,添加,删除和修改控件。还有账号管理,重新登录和退出控件。
(6)创建一个学生信息查找后显示的学生详细信息界面,拥有教师账号的用户可以通过对这个界面信息的修改,按下“修改保存”的控件进行信息的修改。
(7)点击组合框排序,按确定键后,会通过list和文件的操作,进行对应的排序。可以进行的排序为:学号,高数成绩,离散成绩,c++课设成绩,英语成绩,体育成绩。排序后的内容会直接显示在学生成绩管理的主界面list中。
(8)用单文档对学生成绩储存的文件进行操作,并进行直方图和折线图的绘画。在学生成绩管理住界面点击统计分析,可以直接调用该单文档exe.
(8)创建一个重新登录界面,用户可以通过重新登录的方法进行该学生成绩管理系统用户的更换。该界面需要输入学号,旧密码,新密码,再次输入新密码才能修改该账号的密码。
(9)创建一个登录账号管理界面,只有admin的管理员账号才能进行账号的添加,修改和删除。
三实验设备
Win7操作系统
Microsoft Visual Studio2013
四、实验要求
1. 使用MFC类库编制应用程序:按钮控件、静态控件及编辑框的应用。
2. 了解MFC类的层次结构及主要类的用法,掌握使用MFC和向导来编写Windows应用程序。
3掌握静态控件、按钮、流动条、编辑框、列表框、组合框和对话框的创建、消息发送和控件控制等内容。
4对前面所学知识的总结,通过一个比较完整的应用程序的设计,将学过的知识连贯起来,掌握开发一个实际应用程序的步骤,同时学会使用开发工具实现界面友好的应用程序。并通过本实验,掌握如何运用面向对象技术对具体的应用系统进行分析和设计。
五、实验程序
(1)登录界面
LoginDlg.cpp的主要关键代码
//在主界面调用之前在BOOL CMFC课设学生成绩管理系统App::InitInstance()
中添加
CLoginDlg dl;
if (IDCANCEL == dl.DoModal())
return FALSE;
功能是实现先调用登录窗口。
void CLoginDlg::OnBnClickedOk() //点击登录的响应函数
{
if (CheckSuer()) //登录账号和密码的确定是否正确
CDialog::OnOK();
else
{
AfxMessageBox("用户名或密码错误"); //密码错误则弹出窗口提示错误
SetDlgItemText(IDC_NAME, ""); //重置两个编辑框
SetDlgItemText(IDC_PASS, "");
this->SetFocus();
}
}
bool CLoginDlg::CheckSuer() //账户和密码确认
{
CString szName, szPass;
GetDlgItemText(IDC_NAME, szName);
GetDlgItemText(IDC_PASS, szPass);
szName.MakeLower();
if (szName == "admin"&&szPass == "123") //是否为管理员账号
{
SUser u = { "admin", "123", 1 };
theApp.m_us = u; //将登录人员的信息记录在theApp中
return TRUE;
}
SUser u;
CFile file;
if (!file.Open("./user.dat", CFile::modeRead))
{
CreatUser();
if (!file.Open("./user.dat", CFile::modeRead))
return FALSE;
}
while (file.Read(&u, sizeof(u)))
{
if (szName == u.sName&&szPass == u.sPass)
{
theApp.m_us = u;
return TRUE;
}
}
return FALSE;
}
void CLoginDlg::CreatUser() //如果不存在账号和密码存储的文件,则新建一个存储文件
{
CFile file;
if (!file.Open("./user.dat", CFile::modeCreate | CFile::modeWrite))
{
AfxMessageBox("用户文件创建失败");
return;
}
}
(2)学生成绩管理主界面
BEGIN_MESSAGE_MAP(CMFC课设学生成绩管理系统Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_ManagePower, &CMFC课设学生成绩管理系统Dlg::OnBnClickedManagepower)
ON_BN_CLICKED(IDC_AGAIN_LOGIN, &CMFC课设学生成绩管理系统Dlg::OnBnClickedAgainLogin)
ON_BN_CLICKED(IDC_STUDENT_ADD, &CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentAdd)
ON_BN_CLICKED(IDC_STUDENT_DEL, &CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentDel)
ON_BN_CLICKED(IDC_STUDENT_SEEK, &CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentSeek)
ON_BN_CLICKED(IDC_STUDENT_CHANGE, &CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentChange)
ON_BN_CLICKED(IDC_BUTTON8, &CMFC课设学生成绩管理系统Dlg::OnBnClickedButton8)
ON_BN_CLICKED(IDC_STUDENT_IDCANCEL, &CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentIdcancel)
ON_BN_CLICKED(IDC_STUDENT_DIALOG_OKSORT, &CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentDialogOksort)
ON_BN_CLICKED(IDC_PICTURE_ANALYSIS, &CMFC课设学生成绩管理系统Dlg::OnBnClickedPictureAnalysis)
END_MESSAGE_MAP()
// CMFC课设学生成绩管理系统Dlg 消息处理程序
BOOL CMFC课设学生成绩管理系统Dlg::OnInitDialog() //初始化窗口
{
CDialogEx::OnInitDialog();
CString str = "1606100*** 卟咚君 学生成绩管理系统 用户:"; //在窗口左上角设置自己的姓名和学号(课设要求),以及本次显示登录的账号
str += theApp.m_us.sName;
SetWindowText(str);
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_STUDENT_DIALOG_LIST); // 初始化(IDC_STUDENT_DIALOG)ListCtrl控件
pList->InsertColumn(0, "体育", 0, 80);
pList->InsertColumn(0, "英语", 0, 80);
pList->InsertColumn(0, " c++", 0, 80);
pList->InsertColumn(0, "离散", 0, 80);
pList->InsertColumn(0, "高数", 0, 80);
pList->InsertColumn(0, "姓名", 0, 100);
pList->InsertColumn(0, "学号", 0, 100);
SortStudent(0);
ReadStudent(pList);
CComboBox* pComb = (CComboBox*)GetDlgItem(IDC_STUDENT_DIALOG_SORTLIST); //设置(IDC_STUDENT_DIALOG)CComboBox控件
pComb->AddString("学号");
pComb->AddString("高数");
pComb->AddString("离散");
pComb->AddString("c++");
pComb->AddString("英语");
pComb->AddString("体育");
pComb->SetCurSel(0);
CComboBox* pComb1 = (CComboBox*)GetDlgItem(IDC_STUDENT_DIALOG_SORTLIST); //获得排列组合控件的信息
int nSel = pComb1->GetCurSel();
GetDlgItem(IDC_STUDENT_ADD)->EnableWindow(theApp.m_us.nPrior); //对应相应的身份权限设置是否屏蔽添加权限
GetDlgItem(IDC_STUDENT_DEL)->EnableWindow(theApp.m_us.nPrior); //对应相应的身份权限设置是否屏蔽删除权限
GetDlgItem(IDC_STUDENT_CHANGE)->EnableWindow(theApp.m_us.nPrior); //对应相应的身份权限设置是否屏蔽修改权限
//pComb->SetItemHeight(25,25);
//GetDlgItem(IDC_ManagePass)->EnableWindow(theApp.m_us.nPrior);
//GetDlgItem(IDC_ManagePower)->EnableWindow(theApp.m_us.nPrior);
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CMFC课设学生成绩管理系统Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CMFC课设学生成绩管理系统Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFC课设学生成绩管理系统Dlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
void CMFC课设学生成绩管理系统Dlg::OnBnClickedManagepower() //“账号管理”控件响应函数,调用 CPower(管理权限)类的窗口
{
CPower dl;
dl.DoModal();
}
void CMFC课设学生成绩管理系统Dlg::OnBnClickedAgainLogin() //“重新登录”控件响应函数
{
CDialog::OnCancel(); //关闭当前的学生成绩管理系统窗口
CLoginDlg dl; //调用登录窗口
if (IDOK == dl.DoModal()) //成功登录返回IDOK,在调用新的学生成绩管理系统窗口
{ //登录退出则返回IDCANCEL
CMFC课设学生成绩管理系统Dlg dlg;
dlg.DoModal();
}
}
void CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentAdd() //“添加”控件响应函数,调用IDD_StudentSpecificAddDlg添加窗口,添加学号和相应成绩信息
{
CStudentSpecificAddDlg dl;
if (IDCANCEL == dl.DoModal())
{
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_STUDENT_DIALOG_LIST); //关闭IDD_StudentSpecificAddDlg添加窗口,读取储存学生成绩的文件刷新学生成绩管理系统窗口
CMFC课设学生成绩管理系统Dlg::ReadStudent(pList);
OnBnClickedStudentDialogOksort();
}
}
void CMFC课设学生成绩管理系统Dlg::ReadStudent(CListCtrl* pList) //读取储存学生成绩的文件,并加载在学生成绩管理系统窗口的CListCtrl中
{
CFile file;
if (!file.Open("./studentfile.dat", CFile::modeRead | CFile::shareDenyNone))
{
GreatStudentfile();
return;
}
pList->DeleteAllItems();
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
pList->InsertItem(i, u.sId);
pList->SetItemText(i, 1, u.sName);
pList->SetItemText(i, 2, u.sHigher_math);
pList->SetItemText(i, 3, u.sDiscrete_math);
pList->SetItemText(i, 4, u.sC_program);
pList->SetItemText(i, 5, u.sEnglish);
pList->SetItemText(i, 6, u.sSports);
i++;
}
file.Close();
}
void CMFC课设学生成绩管理系统Dlg::GreatStudentfile() //创建用户登录账号储存文件
{
CFile file;
if (!file.Open("./studentfile.dat", CFile::modeCreate | CFile::modeWrite))
{
AfxMessageBox("用户文件创建失败");
return;
}
file.Close();
}
void CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentDel() // “删除”控件响应函数
{
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_STUDENT_DIALOG_LIST);
Student ur;
int nSel = pList->GetSelectedCount(); //获取当前鼠标选择的学号数量
if (nSel < 1)
{
AfxMessageBox("请选择一个账户再删除!");
return;
}
int nSelText = pList->GetSelectionMark(); //获取当前鼠标选择的一个学号位置
pList->GetItemText(nSelText, 0, ur.sId, sizeof(ur.sId));
pList->DeleteItem(nSelText); //删除当前鼠标选择的学号位置
CFile file;
if (!file.Open("./studentfile.dat", CFile::modeRead | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开!");
return;
}
CFile temporaryfile;
if (!temporaryfile.Open("./temporarystudentfile.dat", CFile::modeCreate|CFile::modeWrite| CFile::shareDenyNone))
{
GreatTemporaryStudentfile();
return;
}
Student u;
while (file.Read(&u, sizeof(u)) == sizeof(u)) //读取学生成绩储存文件,将未删除的学生信息写入临时文件temporaryfile中
{
if ((CString)u.sId == (CString)ur.sId)
continue;
temporaryfile.Write(&u, sizeof(u));
}
file.Close();
temporaryfile.Close();
if (!file.Open("./studentfile.dat", CFile::modeCreate|CFile::modeWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开!");
return;
}
if (!temporaryfile.Open("./temporarystudentfile.dat", CFile::modeRead | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开!");
return;
}
while (temporaryfile.Read(&u, sizeof(u)) == sizeof(u)) //读取学生成绩储存文件,将临时文件temporarystudentfile.dat中学生信息写入真正存储学生信息的studentfile.dat中
file.Write(&u, sizeof(u));
CMFC课设学生成绩管理系统Dlg::ReadStudent(pList); //更新学生成绩管理系统界面的信息
OnBnClickedStudentDialogOksort();
return;
}
void CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentSeek() //“查找”控件对应的函数,查找学生的学号
{
int nNum;
char str[20];
GetDlgItemText(IDC_STUDENT_DIALOG_ID, str, sizeof(str)); //获取编辑框的学号信息
if ((CString)str == "")
{
AfxMessageBox("请在学号框里输入学号!");
return;
}
nNum = Seek_Student(str); //查询该学号是否存在
if (nNum == -1)
{
AfxMessageBox("该用户不存在!");
}
Student u;
CFile file;
if (!file.Open("./studentfile.dat", CFile::modeRead | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开!");
return;
}
while (file.Read(&u, sizeof(u)) == sizeof(u)) //查询该学号同学的详细信息
{
if ((CString)u.sId == (CString)str)
{
theApp.m_student = u;
file.Close();
CStudentSpecificSeekDlg dlg; //将该学号同学的详细信息显示在详细信息窗口(IDD_STUDENT_SPECIFIC_DIALOG)
if (IDCANCEL == dlg.DoModal())
{
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_STUDENT_DIALOG_LIST); //更新学生成绩管理系统界面的信息
CMFC课设学生成绩管理系统Dlg::ReadStudent(pList);
}
return;
}
}
file.Close();
}
int CMFC课设学生成绩管理系统Dlg::Seek_Student(char *str) //查询该同学是否存在学生成绩管理系统的CListCtrl中
{
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_STUDENT_DIALOG_LIST);
int nCount = pList->GetItemCount();
int i = 0;
while (i < nCount)
{
if (pList->GetItemText(i, 0) == (CString)str)
{
return i;
}
i++;
}
return -1;
}
void CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentChange() //"修改“控件响应的函数,修改学生的信息
{
OnBnClickedStudentSeek(); //调用查找函数,修改在查找函数中实现
}
void CMFC课设学生成绩管理系统Dlg::OnBnClickedButton8() //"退出”控件响应函数,退出学生成绩管理系统
{
CDialog::OnCancel();
}
void CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentIdcancel()
{
CDialog::OnCancel();
}
void CMFC课设学生成绩管理系统Dlg::GreatTemporaryStudentfile() //创建临时存储学生信息的文件
{
CFile file;
if (!file.Open("./temporarystudentfile.dat", CFile::modeCreate | CFile::modeWrite))
{
AfxMessageBox("用户文件创建失败");
return;
}
file.Close();
}
void CMFC课设学生成绩管理系统Dlg::OnBnClickedStudentDialogOksort() //排序"确定”控件响应函数,进行(学号,高数,离散,c++课设,英语,体育成绩)的排序
{
CComboBox* pComb = (CComboBox*)GetDlgItem(IDC_STUDENT_DIALOG_SORTLIST);
int nSel = pComb->GetCurSel();
SortStudent(nSel);
}
bool nsort_id(Student a, Student b) //学号(ID)大小比较函数
{
return _ttoi((CString)a.sId)<_ttoi((CString)b.sId); //将char转换成CString,在转化成int
}
bool sort_higher_math(Student a, Student b)
{
return _ttoi((CString)a.sHigher_math)>_ttoi((CString)b.sHigher_math); //高数(Higher_math)大小比较函数
}
bool sort_discrete_math(Student a, Student b)
{
return _ttoi((CString)a.sDiscrete_math) > _ttoi((CString)b.sDiscrete_math); //离散(Discrete_math)大小比较函数
}
bool sort_c_program(Student a, Student b)
{
return _ttoi((CString)a.sC_program) > _ttoi((CString)b.sC_program); //c++(C_program)大小比较函数
}
bool sort_english(Student a, Student b)
{
return _ttoi((CString)a.sEnglish) > _ttoi((CString)b.sEnglish); //英语(English)大小比较函数
}
bool sort_sports(Student a, Student b)
{
return _ttoi((CString)a.sSports)> _ttoi((CString)b.sSports); //英语(Sports)大小比较函数
}
void CMFC课设学生成绩管理系统Dlg::SortStudent(int nNum) //对应排序对学生信息进行排序
{
Student SomeStudent[1000];
CFile file;
if (!file.Open("./studentfile.dat", CFile::modeRead | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法排序!");
return;
}
int i = 0;
while (file.Read(&SomeStudent[i], sizeof(SomeStudent[i])) == sizeof(SomeStudent[i]))
{
i++;
}
file.Close();
int b = (CString)SomeStudent[0].sId < (CString)SomeStudent[1].sId;
if (nNum == 0) //0是学号成绩排序
std::sort(SomeStudent, SomeStudent+i, nsort_id); //排序是直接调用STL中的快排
if (nNum == 1) //1是高数成绩排序
std::sort(SomeStudent, SomeStudent + i, sort_higher_math);
if (nNum == 2) //2是离散成绩排序
std::sort(SomeStudent, SomeStudent + i, sort_discrete_math);
if (nNum == 3) //3是C++课设成绩排序
std::sort(SomeStudent, SomeStudent + i, sort_c_program);
if (nNum == 4) //4是英语成绩排序
std::sort(SomeStudent, SomeStudent + i, sort_english);
if (nNum == 5) //5是体育成绩排序
std::sort(SomeStudent, SomeStudent + i, sort_sports);
if (!file.Open("./studentfile.dat", CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法排序!");
return;
}
int t = 0;
while (t
(3)添加学生信息的窗口
BEGIN_MESSAGE_MAP(CStudentSpecificAddDlg, CDialog)
ON_BN_CLICKED(IDC_STUDENG_SPECIFIC_ADD_SAVE, &CStudentSpecificAddDlg::OnBnClickedStudengSpecificAddSave)
ON_BN_CLICKED(IDC_STUDENG_SPECIFIC_ADD_INCANCE, &CStudentSpecificAddDlg::OnBnClickedStudengSpecificAddIncance)
END_MESSAGE_MAP()
// CStudentSpecificAddDlg 消息处理程序
BOOL CStudentSpecificAddDlg::OnInitDialog()
{
CDialog::OnInitDialog();
return TRUE;
}
void CStudentSpecificAddDlg::OnBnClickedStudengSpecificAddSave() //"添加保存:控件响应函数
{
// TODO: 在此添加控件通知处理程序代码
Student u;
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADD_ID, u.sId, sizeof(u.sId)); //将学号编辑框的内容写入u.sId
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADD_NAME, u.sName, sizeof(u.sName)); //将姓名编辑框的内容写入u.sName
if (IDC_STUDENG_SPECIFIC_ADD_MALE == GetCheckedRadioButton(IDC_STUDENG_SPECIFIC_ADD_MALE, IDC_STUDENG_SPECIFIC_ADD_FEMALE))
u.nSex = true;
else
u.nSex = false;
//IDC_STUDENG_SPECIFIC_ADD_MALE为“男”控件ID,IDC_STUDENG_SPECIFIC_ADD_FEMALE为“女'控件的ID
//用GetCheckedRadioButton函数获取RadioButton控件的信息,GetCheckedRadioButton(IDC_STUDENG_SPECIFIC_ADD_MALE, IDC_STUDENG_SPECIFIC_ADD_FEMALE)返回
//IDC_STUDENG_SPECIFIC_ADD_MALE则为男,否则为女
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADD_AGE, u.sAge, sizeof(u.sAge)); //将年龄编辑框的内容写入u.sAge
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADD_ADDRESS, u.sAddress, sizeof(u.sAddress)); //将地址编辑框的内容写入u.sAddress
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADD_HIGHERMATH, u.sHigher_math, sizeof(u.sHigher_math)); //将高数编辑框的内容写入u.sHigher_math
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADD_DISCRETEMATH, u.sDiscrete_math, sizeof(u.sDiscrete_math)); //将离散编辑框的内容写入u.sDiscrete_math
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADD_CPROGRAM, u.sC_program, sizeof(u.sC_program)); //将C++课设编辑框的内容写入u.sC_program
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADD_ENGLISH, u.sEnglish, sizeof(u.sEnglish)); //将英语编辑框的内容写入u.sEnglish
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADD_SPORTS, u.sSports, sizeof(u.sSports)); //将体育编辑框的内容写入u.sSports
CFile file;
if (!file.Open("./studentfile.dat", CFile::modeReadWrite|CFile::shareDenyNone))
{
AfxMessageBox("添加失败,文件打不开!");
return ;
}
Student ur;
while (file.Read(&ur, sizeof(ur))) //读取学生文件信息,看学号是否重复
{
if ((CString)ur.sId == (CString)u.sId)
{
AfxMessageBox("用户已存在!");
return;
}
}
file.SeekToEnd(); //将指针移到文件末尾
file.Write(&u, sizeof(u)); //在文件末尾写入新的学生信息
AfxMessageBox("添加保存成功!"); //提示保存成功
}
void CStudentSpecificAddDlg::OnBnClickedStudengSpecificAddIncance() //“退出”控件响应函数,退出添加窗口
{
CDialog::OnCancel();
// TODO: 在此添加控件通知处理程序代码
}
(4)查找和删除窗口
BEGIN_MESSAGE_MAP(CStudentSpecificSeekDlg, CDialog)
ON_BN_CLICKED(IDOK, &CStudentSpecificSeekDlg::OnBnClickedOk)
ON_BN_CLICKED(IDC_STUDENG_SPECIFIC_CHANGE_SAVE, &CStudentSpecificSeekDlg::OnBnClickedStudengSpecificChangeSave)
ON_BN_CLICKED(IDC_STUDENG_SPECIFIC_IDCACEL, &CStudentSpecificSeekDlg::OnBnClickedStudengSpecificIdcacel)
END_MESSAGE_MAP()
// CStudentSpecificSeekDlg 消息处理程序
BOOL CStudentSpecificSeekDlg::OnInitDialog()
{
CDialog::OnInitDialog();
GetDlgItem(IDC_STUDENG_SPECIFIC_CHANGE_SAVE)->EnableWindow(theApp.m_us.nPrior); //获取账号的权限信息,是否屏蔽“删除”控件
SetDlgItemText(IDC_STUDENG_SPECIFIC_ID,theApp.m_student.sId); //设置显示的学生的学号
SetDlgItemText(IDC_STUDENG_SPECIFIC_NAME, theApp.m_student.sName); //设置显示的学生的姓名
if (theApp.m_student.nSex==1)
CheckRadioButton(IDC_STUDENG_SPECIFIC_MALE, IDC_STUDENG_SPECIFIC_FEMALE, IDC_STUDENG_SPECIFIC_MALE);
else
CheckRadioButton(IDC_STUDENG_SPECIFIC_MALE, IDC_STUDENG_SPECIFIC_FEMALE, IDC_STUDENG_SPECIFIC_FEMALE);
//设置显示的学生的性别
//用CheckRadioButton设置RadioButton的显示
SetDlgItemText(IDC_STUDENG_SPECIFIC_AGE, theApp.m_student.sAge); //设置显示的学生的年龄
SetDlgItemText(IDC_STUDENG_SPECIFIC_ADDRESS, theApp.m_student.sAddress); //设置显示的学生的地址
SetDlgItemText(IDC_STUDENG_SPECIFIC_HIGHERMATH, theApp.m_student.sHigher_math);//设置显示的学生的高数成绩
SetDlgItemText(IDC_STUDENG_SPECIFIC_DISCRETEMATH, theApp.m_student.sDiscrete_math);//设置显示的学生的离散成绩
SetDlgItemText(IDC_STUDENG_SPECIFIC_CPROGRAM, theApp.m_student.sC_program);//设置显示的学生的c++课设成绩
SetDlgItemText(IDC_STUDENG_SPECIFIC_ENGLISH, theApp.m_student.sEnglish);//设置显示的学生的英语成绩
SetDlgItemText(IDC_STUDENG_SPECIFIC_SPORTS, theApp.m_student.sSports);//设置显示的学生的体育成绩
return TRUE;
}
void CStudentSpecificSeekDlg::OnBnClickedOk() //"退出“控件响应函数
{
// TODO: 在此添加控件通知处理程序代码
CDialog::OnOK();
}
void CStudentSpecificSeekDlg::OnBnClickedStudengSpecificChangeSave() //"修改”控件响应函数
{
// TODO: 在此添加控件通知处理程序代码
Student u;
GetDlgItemText(IDC_STUDENG_SPECIFIC_ID, u.sId, sizeof(u.sId)); //将新的信息写入u(Student)中
GetDlgItemText(IDC_STUDENG_SPECIFIC_NAME, u.sName, sizeof(u.sName));
if (IDC_STUDENG_SPECIFIC_MALE == GetCheckedRadioButton(IDC_STUDENG_SPECIFIC_MALE, IDC_STUDENG_SPECIFIC_FEMALE))
u.nSex = true;
else
u.nSex = false;
GetDlgItemText(IDC_STUDENG_SPECIFIC_AGE, u.sAge, sizeof(u.sAge));
GetDlgItemText(IDC_STUDENG_SPECIFIC_ADDRESS, u.sAddress, sizeof(u.sAddress));
GetDlgItemText(IDC_STUDENG_SPECIFIC_HIGHERMATH, u.sHigher_math, sizeof(u.sHigher_math));
GetDlgItemText(IDC_STUDENG_SPECIFIC_DISCRETEMATH, u.sDiscrete_math, sizeof(u.sDiscrete_math));
GetDlgItemText(IDC_STUDENG_SPECIFIC_CPROGRAM, u.sC_program, sizeof(u.sC_program));
GetDlgItemText(IDC_STUDENG_SPECIFIC_ENGLISH, u.sEnglish, sizeof(u.sEnglish));
GetDlgItemText(IDC_STUDENG_SPECIFIC_SPORTS, u.sSports, sizeof(u.sSports));
CFile file;
//file.Open("./studentfile.dat", CFile::modeWrite | CFile::shareDenyNone);
if ((CString)u.sId != (CString)theApp.m_student.sId)
{
AfxMessageBox("请输入同一学号!");
SetDlgItemText(IDC_STUDENG_SPECIFIC_ID, theApp.m_student.sId);
return;
}
if (!file.Open("./studentfile.dat", CFile::modeRead | CFile::shareDenyNone))
{
AfxMessageBox("修改失败,文件打不开!");
return;
}
int i = 0;
Student ur;
while (file.Read(&ur, sizeof(ur))) //读取学生成绩储存文件,找到该学生信息储存的对应位置
{
if ((CString)theApp.m_student.sId == (CString)ur.sId)
{
break;
}
i++;
}
file.Close();
if (!file.Open("./studentfile.dat", CFile::modeWrite | CFile::shareDenyNone))
{
AfxMessageBox("修改失败,文件打不开!");
return;
}
file.SeekToBegin(); // 重新设置file文件的写指针时期刚好在要修改的学生信息那里
file.Seek(i*sizeof(u), CFile::current);
file.Write(&u, sizeof(u)); //用新的信息对原来的信息进行覆盖,实现修改
AfxMessageBox("修改保存成功!");
file.Close();
}
void CStudentSpecificSeekDlg::OnBnClickedStudengSpecificIdcacel() // "退出“控件响应函数
{
CDialog::OnCancel();
// TODO: 在此添加控件通知处理程序代码
}
(5)“账号管理”窗口
BEGIN_MESSAGE_MAP(CPower, CDialog)
ON_BN_CLICKED(IDC_ManagePass, &CPower::OnBnClickedManagepass)
ON_BN_CLICKED(IDC_ChangePass, &CPower::OnBnClickedChangepass)
ON_BN_CLICKED(IDC_MANAGE_CHANGE_PASS, &CPower::OnBnClickedManageChangePass)
ON_BN_CLICKED(IDC_GENERAL_CHANGE_PASS, &CPower::OnBnClickedGeneralChangePass)
ON_BN_CLICKED(IDCANCEL, &CPower::OnBnClickedCancel)
END_MESSAGE_MAP()
// CPower 消息处理程序
void CPower::OnBnClickedManagepass() //“学号密码添加与删除”控件响应函数,调用管理员窗口,进行学号密码添加与删除
{
// TODO: 在此添加控件通知处理程序代码
CManagePower dl;
dl.DoModal();
}
void CPower::OnBnClickedChangepass()
{
// TODO: 在此添加控件通知处理程序代码
}
void CPower::OnBnClickedManageChangePass() //“学号密码添加与删除”控件响应函数,调用管理员(CManagePower)窗口,进行学号密码的修改
{
CManagePower dl;
dl.DoModal();
// TODO: 在此添加控件通知处理程序代码
}
void CPower::OnBnClickedGeneralChangePass() //“学号密码修改”控件响应函数,调用密码修改(CChangePass)窗口,学生和教师权限的账号可通过这个进行学号密码的修改
{
CChangePass dl;
dl.DoModal();
// TODO: 在此添加控件通知处理程序代码
}
BOOL CPower::OnInitDialog() //账号管理窗口的初始化,根据用户的权限是否屏蔽“学号密码添加与删除”控件
{
CDialog::OnInitDialog();
GetDlgItem(IDC_MANAGE_CHANGE_PASS)->EnableWindow((CString)theApp.m_us.sName=="admin");
return TRUE;
}
void CPower::OnBnClickedCancel() //“退出”控件响应函数,退出账号管理窗口
{
// TODO: 在此添加控件通知处理程序代码
CDialog::OnCancel();
}
(6)学号密码修改窗口
BEGIN_MESSAGE_MAP(CChangePass, CDialog)
ON_BN_CLICKED(IDC_OKCHANGE_PASS, &CChangePass::OnBnClickedOkchangePass)
END_MESSAGE_MAP()
// CChangePass 消息处理程序
BOOL CChangePass::Check_ChangePass() //修改“确定”控件响应函数
{
CString szName, szOrdedPass, szNewPassOne, szNewPasstwo; //获取要修改的学号和密码
GetDlgItemText(IDC_CHANGEPASS_NAME, szName);
GetDlgItemText(IDC_CHANGEPASS_ORDEDPASS, szOrdedPass);
GetDlgItemText(IDC_CHANGEPASS_NEWPASS_ONE, szNewPassOne);
GetDlgItemText(IDC_CHANGEPASS_NEWPASS_TWO, szNewPasstwo);
szName.MakeLower();
SUser u;
CFile file;
if (!file.Open("./user.dat", CFile::modeReadWrite))
{
return FALSE;
}
int i = 0;
while (file.Read(&u, sizeof(u))) //两次输入新密码的确认
{
if (szName == (CString)u.sName&&szOrdedPass == (CString)u.sPass)
{
if (szNewPassOne != szNewPasstwo)
{
AfxMessageBox("新密码两次输入不正确!");
InitCCangePassDialog();
}
strcpy_s(u.sPass, szNewPassOne);
file.SeekToBegin();
file.Seek(i*sizeof(u), CFile::current);
file.Write(&u, sizeof(u));
AfxMessageBox("修改成功!");
InitCCangePassDialog();
return TRUE;
}
i++;
}
AfxMessageBox("该用户或旧密码不正确!");
InitCCangePassDialog();
return FALSE;
}
void CChangePass::OnBnClickedOkchangePass() //修改“确定”控件响应函数
{
Check_ChangePass();
// TODO: 在此添加控件通知处理程序代码
}
void CChangePass::InitCCangePassDialog() //重置学号密码修改窗口的编辑框
{
SetDlgItemText(IDC_CHANGEPASS_NAME, "");
SetDlgItemText(IDC_CHANGEPASS_ORDEDPASS, "");
SetDlgItemText(IDC_CHANGEPASS_NEWPASS_ONE, "");
SetDlgItemText(IDC_CHANGEPASS_NEWPASS_TWO, "");
this->SetFocus();
}
(6)学号密码添加与删除窗口
BEGIN_MESSAGE_MAP(CManagePower, CDialog)
ON_CBN_SELCHANGE(IDC_MANAGEPOWER_POWER, &CManagePower::OnCbnSelchangeManagepowerPower)
ON_EN_CHANGE(IDC_MANAGEPOWER_PASS, &CManagePower::OnEnChangeManagepowerPass)
ON_BN_CLICKED(IDC_ADD, &CManagePower::OnBnClickedAdd)
ON_BN_CLICKED(IDCANCEL, &CManagePower::OnBnClickedCancel)
ON_BN_CLICKED(IDC_DEL, &CManagePower::OnBnClickedDel)
ON_BN_CLICKED(IDC_CHANGE, &CManagePower::OnBnClickedChange)
ON_EN_CHANGE(IDC_MANAGEPOWER_NAME, &CManagePower::OnEnChangeManagepowerName)
END_MESSAGE_MAP()
// CManagePower 消息处理程序
BOOL CManagePower::OnInitDialog() //学号密码添加与删除窗口的初始化
{
CDialog::OnInitDialog();
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_MANAGEPOWER_LIST);
pList->InsertColumn(0, "身份", 0, 100); //学号密码添加与删除窗口中CListCtrl(IDC_MANAGEPOWER_LIST)初始化
pList->InsertColumn(0, "密码", 0, 100);
pList->InsertColumn(0, "学号", 0, 100);
ReadUser(pList);
CComboBox* pComb = (CComboBox*)GetDlgItem(IDC_MANAGEPOWER_POWER);
pComb->AddString("学生"); ////学号密码添加与删除窗口中CComboBox(IDC_MANAGEPOWER_POWER)初始化
pComb->AddString("老师");
pComb->SetCurSel(0);
return TRUE;
}
void CManagePower::OnCbnSelchangeManagepowerPower()
{
// TODO: 在此添加控件通知处理程序代码
}
void CManagePower::OnEnChangeManagepowerPass()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CDialog::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
}
void CManagePower::OnBnClickedAdd() //"添加“控件响应函数,添加新的用户账号
{
// TODO: 在此添加控件通知处理程序代码
SUser u;
GetDlgItemText(IDC_MANAGEPOWER_NAME, u.sName, sizeof(u.sName)); //获取账号编辑框的信息
strlwr(u.sName); //u.sName大写转小写
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_MANAGEPOWER_LIST); //获取密码编辑框的信息
int i = 0;
int nCount = pList->GetItemCount(); //获取权限的信息
while (i < nCount)
{
if (pList->GetItemText(i, 0) == u.sName) //检验是否存在该用户
{
AfxMessageBox("用户已存在");
return;
}
i++;
}
pList->InsertItem(nCount, u.sName); //将新用户的信息添加入列表
GetDlgItemText(IDC_MANAGEPOWER_PASS, u.sPass, sizeof(u.sPass));
pList->SetItemText(nCount, 1, u.sPass);
CComboBox* pComb = (CComboBox*)GetDlgItem(IDC_MANAGEPOWER_POWER);
int nSel = pComb->GetCurSel();
if (nSel)
pList->SetItemText(nCount, 2, "老师");
else
pList->SetItemText(nCount, 2, "学生");
}
void CManagePower::OnBnClickedCancel() //”退出“控件响应函数
{
// TODO: 在此添加控件通知处理程序代码
OnDestroy(); //退出前进行保存
CDialog::OnCancel();
}
void CManagePower::OnDestroy() //关闭学号密码添加与删除窗口,关闭之前先将列表的信息保存在账户信息文件中
{
CDialog::OnDestroy();
CFile file;
if (!file.Open("./user.dat", CFile::modeCreate | CFile::modeWrite))
{
AfxMessageBox("保存文件时失败!");
return;
}
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_MANAGEPOWER_LIST);
int i = 0;
int nCount = pList->GetItemCount();
SUser u;
while (i < nCount)
{
pList->GetItemText(i, 0, u.sName, sizeof(u.sName));
pList->GetItemText(i, 1, u.sPass, sizeof(u.sPass));
u.nPrior = pList->GetItemText(i, 2) == "老师";
file.Write(&u, sizeof(u));
i++;
}
file.Close();
AfxMessageBox("保存文件成功!");
}
void CManagePower::ReadUser(CListCtrl* pList) //读取学生成绩存储文件,将其显示在学号密码添加与删除窗口CListCtrl中
{
CFile file;
if (!file.Open("./user.dat", CFile::modeRead | CFile::shareDenyNone))
return;
pList->DeleteAllItems();
SUser u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
pList->InsertItem(i, u.sName);
pList->SetItemText(i, 1, u.sPass);
pList->SetItemText(i, 2, u.nPrior ? "老师" : "学生");
i++;
}
file.Close();
}
void CManagePower::OnBnClickedDel() //”删除“控件响应函数
{
// TODO: 在此添加控件通知处理程序代码
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_MANAGEPOWER_LIST);
SUser u;
GetDlgItemText(IDC_MANAGEPOWER_NAME, u.sName, sizeof(u.sName));
strlwr(u.sName);
int nSel = pList->GetSelectedCount(); //选择一个账户
if (nSel < 1&&u.sName=="")
{
AfxMessageBox("请选择一个账户再删除!");
return;
}
if (nSel < 1 && (CString)u.sName != "")
{
int i = 0;
int nCount = pList->GetItemCount();
SUser ur;
while (i < nCount)
{
pList->GetItemText(i, 0, ur.sName, sizeof(ur.sName));
pList->GetItemText(i, 1, ur.sPass, sizeof(ur.sPass));
ur.nPrior = pList->GetItemText(i, 2) == "老师";
if ((CString)u.sName == (CString)ur.sName)
{
pList->DeleteItem(i);
return;
}
i++;
}
AfxMessageBox("该账户不存在!");
return;
}
else
{
if (nSel >= 1 && (CString)u.sName == "")
{
int nSelText = pList->GetSelectionMark();
pList->DeleteItem(nSelText);
}
else
{
int nSelText = pList->GetSelectionMark();
SUser ur;
pList->GetItemText(nSelText, 0, ur.sName, sizeof(ur.sName));
if ((CString)ur.sName == (CString)u.sName)
pList->DeleteItem(nSelText);
else
{
AfxMessageBox("请选择同一个账户再删除!");
return;
}
}
}
}
void CManagePower::OnBnClickedChange() //"修改“控件响应函数
{
// TODO: 在此添加控件通知处理程序代码
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_MANAGEPOWER_LIST);//获取需要更改信息
SUser u;
GetDlgItemText(IDC_MANAGEPOWER_NAME, u.sName, sizeof(u.sName));
GetDlgItemText(IDC_MANAGEPOWER_PASS, u.sPass, sizeof(u.sPass));
strlwr(u.sName);
CComboBox* pComb = (CComboBox*)GetDlgItem(IDC_MANAGEPOWER_POWER);
u.nPrior = pComb->GetCurSel();
int nSel = pList->GetSelectedCount();
if (nSel < 1 && u.sName == "")
{
AfxMessageBox("请选择一个账户再!");
return;
}
if (nSel < 1 && (CString)u.sName != "") //进行账户密码信息更改
{
int i = 0;
int nCount = pList->GetItemCount();
SUser ur;
while (i < nCount)
{
pList->GetItemText(i, 0, ur.sName, sizeof(ur.sName));
pList->GetItemText(i, 1, ur.sPass, sizeof(ur.sPass));
ur.nPrior = pList->GetItemText(i, 2) == "老师";
if ((CString)u.sName == (CString)ur.sName)
{
pList->DeleteItem(i);
pList->InsertItem(i, u.sName);
pList->SetItemText(i, 1, u.sPass);
pList->SetItemText(i, 2, u.nPrior ? "老师" : "学生");
return;
}
i++;
}
AfxMessageBox("该账户不存在!");
return;
}
else
{
if (nSel >= 1 && (CString)u.sName == "")
{
int nSelText = pList->GetSelectionMark();
SUser ur;
pList->GetItemText(nSelText, 0, ur.sName, sizeof(ur.sName));
pList->DeleteItem(nSelText);
pList->InsertItem(nSelText, ur.sName);
pList->SetItemText(nSelText, 1, u.sPass);
pList->SetItemText(nSelText, 2, u.nPrior ? "老师" : "学生");
}
else
{
int nSelText = pList->GetSelectionMark();
SUser ur;
pList->GetItemText(nSelText, 0, ur.sName, sizeof(u.sName));
if ((CString)ur.sName == (CString)u.sName)
{
pList->DeleteItem(nSelText);
pList->InsertItem(nSelText, ur.sName);
pList->SetItemText(nSelText, 1, u.sPass);
pList->SetItemText(nSelText, 2, u.nPrior ? "老师" : "学生");
}
else
{
AfxMessageBox("请选择同一个账户再删除!");
return;
}
}
}
}
(7)用单文档读取学生成绩文件,进行直方图和折线图的绘画
void CMFCApplication1View::OnDraw(CDC* pDC)
{
CMFCApplication1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
}
// CMFCApplication1View 打印
BOOL CMFCApplication1View::OnPreparePrinting(CPrintInfo* pInfo)
{
// 默认准备
return DoPreparePrinting(pInfo);
}
void CMFCApplication1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加额外的打印前进行的初始化过程
}
void CMFCApplication1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加打印后进行的清理过程
}
// CMFCApplication1View 诊断
#ifdef _DEBUG
void CMFCApplication1View::AssertValid() const
{
CView::AssertValid();
}
void CMFCApplication1View::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMFCApplication1Doc* CMFCApplication1View::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCApplication1Doc)));
return (CMFCApplication1Doc*)m_pDocument;
}
#endif //_DEBUG
// CMFCApplication1View 消息处理程序
void CMFCApplication1View::DrawScore(CDC* pDC, int * fScore, int nNum) //画直方图函数
{
// fScore是成绩数组指针,nNum是学生人数
int nScoreNum[] = { 0, 0, 0, 0, 0 }; // 各成绩段的人数的初 始值
// 下面是用来统计各分数段的人数
for (int i = 0; i < nNum; i++)
{
int nSeg = (int)(fScore[i]) / 10; // 取数的"十"位上的值
if (nSeg < 6) nSeg = 5; // <60分
if (nSeg == 10) nSeg = 9;// 当为100分,算为>90分数段
nScoreNum[nSeg - 5] ++; // 各分数段计数
}
int nSegNum = sizeof(nScoreNum) / sizeof(int); // 计算有多少个分数段
// 求分数段上最大的人数
int nNumMax = nScoreNum[0];
for (int i = 1; i < nSegNum; i++)
{
if (nNumMax < nScoreNum[i])
nNumMax = nScoreNum[i];
}
CRect rc;
GetClientRect(rc);
rc.DeflateRect(180, 40); // 缩小矩形大小
int nSegWidth = rc.Width() / nSegNum; // 计算每段的宽度
int nSegHeight = rc.Height() / nNumMax; // 计算每段的单位高度
COLORREF crSeg = RGB(0, 0, 192); // 定义一个颜色变量
CBrush brush1(HS_FDIAGONAL, crSeg);
CBrush brush2(HS_BDIAGONAL, crSeg);
CPen pen(PS_INSIDEFRAME, 2, crSeg);
CBrush* oldBrush = pDC->SelectObject(&brush1); // 将brush1选入设备环境
CPen* oldPen = pDC->SelectObject(&pen); // 将pen选 入设备环境
CRect rcSeg(rc);
rcSeg.right = rcSeg.left + nSegWidth; // 使每段的矩形宽度等于nSegWidth
CString strSeg[] = { (CString)"<60", (CString)"60-70", (CString)"70-80", (CString)"80-90", (CString)">=90" };
CRect rcStr;
for (int i = 0; iSelectObject(&brush2);
else
pDC->SelectObject(&brush1);
rcSeg.top = rcSeg.bottom - nScoreNum[i] * nSegHeight - 2; // 计算每段矩形的高度
pDC->Rectangle(rcSeg);
if (nScoreNum[i] > 0)
{
CString str;
str.Format((CString)"%d人", nScoreNum[i]);
pDC->DrawText(str, rcSeg, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
rcStr = rcSeg;
rcStr.top = rcStr.bottom + 2;
rcStr.bottom += 20;
pDC->DrawText(strSeg[i], rcStr, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
rcSeg.OffsetRect(nSegWidth, 0); // 右移矩形
}
pDC->SelectObject(oldBrush); // 恢复原来的画刷属性
pDC->SelectObject(oldPen); // 恢复原来的画笔属性
CDC* pControlDC = pDC;
pControlDC->SelectStockObject(BLACK_BRUSH);//设置画刷
CString str;
pControlDC->MoveTo(180, 40); //画y轴
pControlDC->LineTo(180,380);
pControlDC->MoveTo(180, 380);//画x轴
pControlDC->LineTo(900, 380);
}
int CMFCApplication1View::OnCreate(LPCREATESTRUCT lpCreateStruct)// 创建各个成绩显示控件
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
m_button1.Create((CString)"高等数学(直方)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(10, 10, 120, 40), //按钮大小
this, //按钮父指针
IDC_HIGGER_MATH); //该按钮对应的ID号
m_button1.ShowWindow(SW_SHOWNORMAL);
m_button2.Create((CString)"离散数学(直方)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(10, 60,120, 90), //按钮大小
this, //按钮父指针
IDC_DISCRETE_MATH); //该按钮对应的ID号
m_button2.ShowWindow(SW_SHOWNORMAL);
m_button3.Create((CString)"c+课设(直方)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(10, 110, 120, 140), //按钮大小
this, //按钮父指针
IDC_C_PROGRAM); //该按钮对应的ID号
m_button3.ShowWindow(SW_SHOWNORMAL);
m_button4.Create((CString)"大学英语(直方)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(10, 160, 120, 190), //按钮大小
this, //按钮父指针
IDC_ENGLISH); //该按钮对应的ID号
m_button4.ShowWindow(SW_SHOWNORMAL);
m_button5.Create((CString)"大学体育(直方)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(10, 210, 120, 240), //按钮大小
this, //按钮父指针
IDC_SPORTS); //该按钮对应的ID号
m_button5.ShowWindow(SW_SHOWNORMAL);
// TODO: 在此添加您专用的创建代码
m_button6.Create((CString)"(折线)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(120, 10, 170, 40), //按钮大小
this, //按钮父指针
IDC_HIGGER_MATH_LINE); //该按钮对应的ID号
m_button6.ShowWindow(SW_SHOWNORMAL);
m_button7.Create((CString)"(折线)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(120, 60, 170, 90), //按钮大小
this, //按钮父指针
IDC_DISCRETE_MATH_LINE); //该按钮对应的ID号
m_button7.ShowWindow(SW_SHOWNORMAL);
m_button8.Create((CString)"(折线)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(120, 110, 170, 140), //按钮大小
this, //按钮父指针
IDC_C_PROGRAM_LINE); //该按钮对应的ID号
m_button8.ShowWindow(SW_SHOWNORMAL);
m_button9.Create((CString)"(折线)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(120,160 , 170, 190), //按钮大小
this, //按钮父指针
IDC_ENGLISH_LINE); //该按钮对应的ID号
m_button9.ShowWindow(SW_SHOWNORMAL);
m_button10.Create((CString)"(折线)",//按钮标题
WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
CRect(120, 210, 170, 240), //按钮大小
this, //按钮父指针
IDC_SPORTS_LINE); //该按钮对应的ID号
m_button10.ShowWindow(SW_SHOWNORMAL);
return 0;
}
void CMFCApplication1View::OnClickButton_higher_math_show() //高数成绩直方图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sHigher_math);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
DrawScore(GetDC(), m_Num, i);
file.Close();
}
void CMFCApplication1View::OnClickButton_discrete_math_show() //离散成绩直方图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sDiscrete_math);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
DrawScore(GetDC(), m_Num, i);
file.Close();
}
void CMFCApplication1View::OnClickButton_c_program_show() //C++成绩直方图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sC_program);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
DrawScore(GetDC(), m_Num, i);
file.Close();
}
void CMFCApplication1View::OnClickButton_english_show() //英语成绩直方图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sEnglish);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
DrawScore(GetDC(), m_Num, i);
file.Close();
}
void CMFCApplication1View::OnClickButton_sports_show()//体育成绩直方图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sSports);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
DrawScore(GetDC(), m_Num, i);
file.Close();
}
void CMFCApplication1View::Drawlist(CDC* pDC, int* fScore, int nNum)//画折线图
{
// fScore是成绩数组指针,nNum是学生人数
int nScoreNum[] = { 0, 0, 0, 0, 0 }; // 各成绩段的人数的初 始值
// 下面是用来统计各分数段的人数
for (int i = 0; i < nNum; i++)
{
int nSeg = (int)(fScore[i]) / 10; // 取数的"十"位上的值
if (nSeg < 6) nSeg = 5; // <60分
if (nSeg == 10) nSeg = 9;// 当为100分,算为>90分数段
nScoreNum[nSeg - 5] ++; // 各分数段计数
}
CDC* pControlDC = pDC;
pControlDC->SelectStockObject(BLACK_BRUSH);//设置画刷
CString str;
CString strSeg[] = { (CString)"<60", (CString)"60-70", (CString)"70-80", (CString)"80-90", (CString)">=90" };
pControlDC->MoveTo(180, 40);//画线的开始位置
pControlDC->LineTo(180, 380);
pControlDC->MoveTo(180, 380);//画线的开始位置
pControlDC->LineTo(900, 380);
pControlDC->MoveTo(180, 380);
for (int i = 0; i < 5; i++)
{
pControlDC->SetPixel(0, 290, RGB(0, 0, 255)); //设置点的位置及颜色
pControlDC->LineTo(i*140+220, 380 - (380*nScoreNum[i]/nNum));//换两点之间的线
str.Format("%d人", nScoreNum[i]);
pControlDC->TextOut(i * 140 + 220,380 - (380 * nScoreNum[i] / nNum)-20, str);//在线的上方输出文字
pControlDC->TextOut(i * 140 + 220, 390, strSeg[i]);
}
}
void CMFCApplication1View::OnClickButton_higher_math_listshow()//高数成绩折线图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sHigher_math);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
Drawlist(GetDC(), m_Num, i);
file.Close();
}
void CMFCApplication1View::OnClickButton_discrete_math_listshow()//离散成绩折线图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sDiscrete_math);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
Drawlist(GetDC(), m_Num, i);
file.Close();
}
void CMFCApplication1View::OnClickButton_c_program_listshow()//c++课设成绩折线图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sC_program);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
Drawlist(GetDC(), m_Num, i);
file.Close();
}
void CMFCApplication1View::OnClickButton_english_listshow()//英语成绩折线图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sEnglish);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
Drawlist(GetDC(), m_Num, i);
file.Close();
}
void CMFCApplication1View::OnClickButton_sports_listshow()//体育成绩折线图控件按钮对应函数
{
CFile file;
if (!file.Open("e://打编码//MFC//MFC课程设计-学生成绩管理系统//MFC课设-学生成绩管理系统//Debug//studentfile.dat", CFile::modeReadWrite | CFile::shareDenyNone))
{
AfxMessageBox("文件无法打开,无法画图!");
return;
}
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
m_Num[i] = _ttoi((CString)u.sSports);
i++;
}
InvalidateRect(NULL);
UpdateWindow();
Drawlist(GetDC(), m_Num, i);
file.Close();
}
六.实验中的问题和提高
这个学生成绩管理系统中的安全措施并不完善,整个软件也没有加壳,以至于这个软件可以直接被脱壳并找出管理员的登录账号和密码,我目前的能力水平有限,还不能对软件进行加壳加密操作。
这个学生成绩管理系统的用户界面还不是很好看,使用的方面和一般的登录界面还是有点违和感。
七、总结心得
(1)刚开始的课设制作的时候,出现了很多变量的设置,变量一多,就容易搞混,后来,我统一使用了微软标准命名法进行控件和窗口ID以及函数,类,变量的命名。这样在多个窗口的界面开发的过程中才不容易搞混。
(2)在修改文件内容的时候,我想使用file.Seek(-sizeof(u),CFile:: current)进行写指针向前移动,但是出现了内存溢出的问题。我查不出问题出现在那里,后来使用了SeekToBegin()
和file.Seek(i*sizeof(u),CFile:: current)才解决问题,可以在学生成绩的存储文件直接进行覆盖修改。
(3)之前学会了GetDlgItemText()的用法,后来在MFC类库中查询到还有SetDlgItemText()的用法,可以直接在编辑框控件中提取信息,而不用设置变量。
(4)在RadioButton控件的使用中,我不知道如何提取按键和设置按键的信息,后来在网上查到GetCheckedRadioButton(IDC,IDC)和CheckRadioButton(IDC,IDC,IDC)这两个函数才解决问题。
(5)这个学生成绩管理系统的设置,比原本的实验要求高出了很多。我添加了登录管理系统在里面。这个学生管理系统即使面对教师的,也是面对学生的。学生可以快速查询自己的成绩,而教师还能添加,删除和修改学生的成绩,而学生和老师账户可以通过管理员账号添加,删除,和修改。
(6)我在排序中重新定义了六种不同对象比较大小的方法,然后调用STL中的快排函数实行快排。与一般的冒泡之类的排序方法不同的是,快排是通过不断二分插入的方法进行排序的,时间复杂度为nlogn,大大节省了排序时间。
(7)由于我是在一个单文档中通过按钮消息映射绘制五种直方图和五种折线图。在清空界面的时候,我调用了InvalidateRect(NULL)这个函数实行清空操作,但是却出现了连自己将要绘制的图形也清空了的现象,后来添加了UpdateWindow()这个函数才得以解决。
(8)在运用单文档读取文件信息绘制直方图和折线图的时候,要细心修改自己设置的矩形和顶点的参数,以及移动时的参数,使得绘图界面美观整齐。
(9)在学生管理系统中,我设置了统计分析这个控件,调用了ShellExecute这个函数,然后这个函数可以调用我画图的exe文件,因此,我可以在学生管理系统中直接显示学生成绩的直方图和折线图。
(10)大总结:通过对学生成绩管理系统的可视化编程,了解了开发一个实际应用程序的步骤,同时学会使用开发工具实现界面友好的应用程序。通过本实验,掌握如何运用面向对象技术对具体的应用系统进行分析和设计。了解了MFC类的层次结构及主要类的用法,掌握使用MFC和向导来编写Windows应用程序。明白了控件是Windows图形用户界面的主要组成部分之一,掌握静态控件、按钮、流动条、编辑框、列表框、组合框和对话框的创建、消息发送和控件控制的基本用法。看着同学们不断的完成自己的课设,我还是坚持将这个学生成绩管理系统做的更好,通过加入登录和权限限制,让它不仅能服务与老师,同时也能运用于学生,并实行五门成绩的管理和统计绘图。在不断地网上查询资料和在类库中了解函数的方法,才终于完成了这个学生成绩管理系统。