一、 实验目的
- 使用MFC类库编程应用程序:控件按钮、静态控件及编辑框的应用。
- 了解MFC类的层次结构及主要类的方法,掌握使用MFC和向导来编写Windows应用程序。
- 熟悉Microsoft Visual Studio 2017的开发环境。
- 掌握Microsoft Visual Studio 2017开发调试程序的方法。
- 掌握静态控件、按钮、编辑框、按钮控件、下拉框、组合框、对话框的创建、消息映射、响应事件、控件控制等内容。
- 对所学的c++及MFC知识的综合应用,通过一个比较完整的应用程序的设计,掌握开发一个实际应用程序的步骤,同时学会使用开发工具实现界面友好的应用程序。并通过本实验,掌握如何运用面向对象技术对具体的应用系统进行统计分析和设计。
二、 实验内容
应用MFC应用程序实现学生信息管理系统
1、(1)设计一个学生类Student,包括数据成员:姓名、学号、二门课程(面向对象程序设计、高等数学)的成绩。
(2)创建一个管理学生的类Management,包括实现学生的数据的增加、删除、修改、按课程成绩排序、保存学生数据到文件按及加载文件中的数据等功能。
(3)创建一个基于对话框的MFC应用程序,程序窗口的标题上有你的姓名、学号和应用程序名称。使用(1)和(2)中的类,实现对学生信息和成绩的输入和管理。
(4)创建一个单文当的MFC应用程序,读取(3)中保存的文件的学生成绩,分别用直方图和折线图显示所有学生某课程的成绩分布图。
功能展示:打开应用,调出主界面
点击加载数据:可将之前保留的数据显示
添加学生:再点击加载数据
排序:(升序降序皆可)
点击列表头
按数学
按C++
其余功能不赘述。切入正题。
三、 实验步骤及程序代码
1、 打开vs2017->新建项目、创建MFC应用程序->命名,在这里我的是StuInfoManage(关乎对话框的ID名、类名、.cpp、.h名 每个人可按照自己的想法命名)->在应用程序类型下选择基于对话框,其他默认就好->点击完成。
2、 先搞好主界面布局:(其功能之后再实现)
打开资源视图(在视图菜单下,其他窗口/快捷键ctrl+shift+E)->一直展开到dilog文件,找到IDD_STUINFOMANAGE_DIALOG打开,进行控件布局(下图供参考)、取消按钮的caption改成退出管理界面,控件ID没作修改我是默认的。
关于一些控件的设置:
(1)改控件名字,对应控件右键属性,找i到caption,修改即可。
(2)LIst Control:右键属性view要改成report. 接着右键添加变量,类别控件, 变量类型ClistCtrl,名字m_nlist1.
(3)修改信息模块:
为每一个编辑框添加变量
姓名 :m_RName 值 CString
学号:m_RNumber 值 CString
地址:m_RAddress 值 CString
数学成绩:m_RMath 值 CString
c++成绩:m_CProgram 值 CString
年龄:m_RAge 值 CString
(4)Radio buttom:单选按钮 男 女
第一个单选按钮:属性中的:group为true tabstop为true auto为true
第二个单选按钮:对应为 false true true.
添加变量:只为第一个按钮添加m_RSex 值 Bool.
(默认选中第一个m_sSex=0,若选中第二个则m_sSex=1,分组中有多个单选按钮以此类推)
关于不同版本的编译器可能添加变量的界面会有所不同,并且有一些添加变量时没有自动绑定变量与控件。需要手动绑定。在cpp文件下找到函数
模仿着写。
(5)查找模块:
Combo box(下拉框):添加变量、类别控件、变量类型CComboBox、名称m_CCBox
Edit Control:添加变量:值、CString、名称:m_sSearch.
(6)统计人数模块:
Edit Control:添加变量:值、m_Population、CString.
3、 实现每一个按钮的功能:
在实现之前很重要的一点:在<StuInfoManageDlg.h>和<StuInfoManage.h>添加一些c++库头文件,以及自定义的函数名称和变量:
打开解决方案资源管理器–头文件:
——StuInfoManage.h
#include "resource.h" // 主符号
//使用c++的语法
#include <iostream>
#include<fstream>//文件流
#include<cstring>//string类字符串
#include<sstream>//字符串流
#include<iomanip>//格式控制符
#include<cstdlib>
using namespace std;
——StuInfoManageDlg.h
在里面添加:定义之后需要用到的一些函数变量。
//自定义的函数及变量
string name1, number1, sex1, age1, address1, math1, mfc1;
CString Oldnumber;
void SetList(); //将文件内容输出到列表
int item; //存储选中列表项标号
void Print(int x, string s[]);//自定义打印内容到列表项目函数
(1)添加学生信息:
首先添加多一个对话框(用于关联添加学生信息按钮)
在之前的资源视图->添加资源、选中dilog、点击新建(资源视图多一个IDD_DIALOG1)->布局成下图,其中将确定按钮和取消按钮的属性caption改成确认添加和返回管理界面
为这个对话框添加类(这里我设置的类名为ADD)
右键添加类(如图)
这里的编辑框和单选按钮的属性设置以及变量添加:
姓名:值 m_sName CString
学号:值 m_sNumber CString
性别:第一个按钮为caption属性为 男 group、Tabstop、Auto 均为true
另一个为女 group为false 其余为true
而且只为第一个单选按钮添加变量:值 m_sSex BOOL
通讯地址:值 m_sAddress CString
数学成绩:值 m_sMath CString
c++成绩:值 m_sCProgram CString
年龄: 值 m_sAge CString
确认添加按钮的响应事件:
双击该按钮:则会自动创建响应函数
先在响应函数上方写一个保存信息的函数Save():
//保存学生信息到文本 函数
void ADD::savefile(const char *filename)
{
ofstream outfile(filename, ios::app); //保存的时候用追加方式打开文本
if (!outfile) {
MessageBox(CString("文件无法打开!!!")); return; }
else {
outfile << setiosflags(ios::left) << setw(20) << m_name << setiosflags(ios::left) << setw(20) << m_number
<< setiosflags(ios::left) << setw(20) << m_sex << setiosflags(ios::left) << setw(20) << m_address
<< setiosflags(ios::left) << setw(20) << m_math << setiosflags(ios::left) << setw(20) << m_mfc
<< setiosflags(ios::left) << setw(20) << m_age;
}
outfile.put('\n');
outfile.close();
}
接着在响应函数里面写入:
void ADD::OnBnClickedOk()
{
UpdateData(TRUE); //更新编辑框,单选框等信息获取信息到 绑定变量
if (m_sName != "") //判断
{
m_name = CStringA(m_sName); //将CString类数据类型转化为string字符串类,以便可以用流输入输出操作
}
if (m_sNumber != "")
{
m_number = CStringA(m_sNumber);
}
if (m_sAddress != "")
{
m_address = CStringA(m_sAddress);
}
if (m_sMath != "")
{
if (_ttoi(m_sMath) > 151 || _ttoi(m_sMath) < -1) {
MessageBox(_T("该成绩爆表,请再确认一次,有效成绩(0 - 150)")); return; }
m_math = CStringA(m_sMath);
}
if (m_sCProgram != "")
{
if (_ttoi(m_sCProgram) > 151 || _ttoi(m_sCProgram) < -1) {
MessageBox(_T("该成绩爆表,请再确认一次,有效成绩(0 - 150)")); return; }
m_mfc = CStringA(m_sCProgram);
}
if (m_sAge != "")
{
if(_ttoi(m_sAge) > 201 || _ttoi(m_sAge) < -1) {
MessageBox(_T("请输入年龄范围(0 - 200)岁")); return; }
m_age = CStringA(m_sAge);
}
bool flag = true; //判断录入循环的结束
string s1, s2, s3, s4, s5, s6, s7;//存文本读出的数据
ifstream infile(filename, ios::in); //以只读方式打开文本
switch (m_sSex)
{
case 0:m_sex = "男"; break;
case 1:m_sex = "女"; break;
}
if