一、目的:此文通过一个GPA计算器的制作,介绍基于对话框的应用程序的编程方法、常用控件的编程技巧以及控件外观的更改技巧。

二、功能描述:所谓GPA计算器,即进行GPA换算。

  功能要求由如下几点:

  1.学生成绩可以由文件导入。

  2.GPA标准可以选择,也可以手动输入。

  3.GPA的计算过程易于监督控制。

  4.计算结果的可读性强。

三、关键技术与算法:

  1.CFile和CArchive

  CFile是MFC的文件操作基本类,它直接支持无缓冲的二进制磁盘I/O操作,并通过其派生类支持文本文件、内存文件和Socket文件。

  打开文件方法:

CFile(LPCTSTR lpszFileName, UINT nOpenFlags);

其中,lpszFileName表示要打开的文件名,可以是相对路径或绝对路径。

  一个CArchive对象与一个文件相连,充当了文件与要读写的数据结构之间的桥梁和管道的角色。它在文件和要读写的数据结构之间设置了一个缓冲区,提供数据缓冲机制。CArchive的构造函数为:

CArchive(CFile *pFile, UINT nMode, int nBufSize=4096, void *lpBuf=NULL)

其中,pFile表示CArchive所基于的文件,nMode制定CArchive的存取模式。

  本实例用上述两个类完成了对成绩文件的读取。

  2.公共对话框

  本实例用到了CFileDialog,它是文件对话框,提供从磁盘目录结构中选择一个文件的对话框界面(经常用于打开文件或保存文件)。

四、程序实现:

  1.创建项目:项目名为GPACalculator,基于对话框,其他默认。

  2.界面设计:打开对话框资源IDD_GPACALCULATOR_DIALOG,该对话框将是程序运行时的主界面。

  2.1 下面按要求添加控件:

控件类型             ID                          属性设置
Button              IDC_BUTTON_OPEN             Caption设为“浏览...”
Button              IDC_BUTTON_OK               Caption设为“统计”
Static Text         默认                        Caption设为“参比标准”
Static Text         默认                        Caption设为“标准分”
Static Text         默认                        Caption设为“原始分”
Static Text         默认                        Caption设为“统计信息”
Static Text         默认                        Caption设为“分数列表”
Static Text         默认                        Caption设为“加权平均分”
Static Text         默认                        Caption设为“GPA”
Static Text         默认                        Caption设为“总学分”
Edit Box            IDC_EDIT_PATHNAME           默认
Edit Box            IDC_EDIT_S1                 ReadOnly
Edit Box            IDC_EDIT_S2                 ReadOnly
Edit Box            IDC_EDIT_S3                 ReadOnly
Edit Box            IDC_EDIT_S4                 ReadOnly
Edit Box            IDC_EDIT_S5                 ReadOnly
Edit Box            IDC_EDIT_S6                 ReadOnly
Edit Box            IDC_EDIT_S7                 ReadOnly
Edit Box            IDC_EDIT_O1                 ReadOnly
Edit Box            IDC_EDIT_O2                 ReadOnly
Edit Box            IDC_EDIT_O3                 ReadOnly
Edit Box            IDC_EDIT_O4                 ReadOnly
Edit Box            IDC_EDIT_O5                 ReadOnly
Edit Box            IDC_EDIT_O6                 ReadOnly
Edit Box            IDC_EDIT_O7                 ReadOnly
Edit Box            IDC_EDIT_O8                 ReadOnly
Edit Box            IDC_EDIT_AVERAGE            ReadOnly
Edit Box            IDC_EDIT_GPA                ReadOnly
Edit Box            IDC_EDIT_TOTAL              ReadOnly
Group Box           默认                        Caption设为“第一步:载入分数文件”
Group Box           默认                        Caption设为“第二步:设置参比标准”
Group Box           默认                        Caption设为“第三步:统计并显示”
Combo Box           IDC_COMBO_STANDARD          DropList
List Box            IDC_LIST_SCORE              默认

看下效果图:

这里需要说明几点:

1>控件配置表与图片还是比较好对应的。两个按钮及一些静态文本框及三个组框、一个组合框、一个列表框,编辑框有一堆:第一个对应第一步里的那个pathname,然后IDC_EDIT_Sx对应标准分的那七个框框,IDC_EDIT_Ox对应原始分的那八个框框,后面是第三步里的三个编辑框,对应清晰就ok了。

2>至于那个List Box,默认属性里不选择sort(分类),即对于列表框的数据不分类排序。

3>这里得提点下Combo Box的用法。注意在设计ComboBox时,点下向下箭头(小三角形),即(注意看那蓝色的小正方形是否空心):

然后将控件下边(那个实心的小正方形)向下拉,即:

这样才能显示出ComboBox的下拉的项。

  2.2 打开ClassWizard,针对IDD_GPACALCULATOR_DIALOG所指向的类CGPACalculatorDlg,为控件添加类成员变量,按下面的要求:

控件ID                     变量名                 数据类型
IDC_EDIT_PATHNAME         m_sPathName            CString
IDC_EDIT_S1               m_dS1                  double
IDC_EDIT_S2               m_dS2                  double
IDC_EDIT_S3               m_dS3                  double
IDC_EDIT_S4               m_dS4                  double
IDC_EDIT_S5               m_dS5                  double
IDC_EDIT_S6               m_dS6                  double
IDC_EDIT_S7               m_dS7                  double
IDC_EDIT_O1               m_dO1                  double
IDC_EDIT_O2               m_dO2                  double
IDC_EDIT_O3               m_dO3                  double
IDC_EDIT_O4               m_dO4                  double
IDC_EDIT_O5               m_dO5                  double
IDC_EDIT_O6               m_dO6                  double
IDC_EDIT_O7               m_dO7                  double
IDC_EDIT_O8               m_dO8                  double
IDC_EDIT_AVERAGE          m_strAverage           CString
IDC_EDIT_GPA              m_strGPA               CString
IDC_EDIT_TOTAL            m_dTotal               double
IDC_COMBO_STANDARD        m_cmbStandard          CComboBox
IDC_LIST_SCORE            m_ListScore            CListBox

  3.代码编写:

  3.1 添加菜单控制

  3.1.1 制作菜单:vc菜单->插入->资源->选择menu,点击新建->制作如下(选中虚线框,鼠标右键点击属性):

  

其中,“退出”的ID设为ID_MENUITEM_EXIT,“使用说明”的ID设为ID_MENUITEM_MAN,“关于”的ID设为ID_MENUITEM_ABOUT。菜单名字设为IDR_MAIN_MENU。

  3.1.2 装载菜单:打开主界面IDD_GPACALCULATOR_DIALOG的属性对话框,在menu的列表框中选中相应的菜单资源。如下:

  3.1.3 编写菜单代码。使用ClassWizard针对菜单项向对话框类中增加函数。

  1>【使用说明】菜单:

void CGPACalculatorDlg::OnMenuitemMan()
{// TODO: Add your command handler code hereWinExec("notepad.exe EXPLAIN.HEP",SW_SHOW);
}

  2>【关于】菜单:

void CGPACalculatorDlg::OnMenuitemAbout()
{// TODO: Add your command handler code here
    CAboutDlg dlg;dlg.DoModal();
}

  3>【退出】菜单:

void CGPACalculatorDlg::OnMenuitemExit()
{// TODO: Add your command handler code here
    DestroyWindow();
}

  3.2 分数存储结构

  在GPACalculatorDlg.h里添加读取分数的数据结构:

typedef struct stScore{double dOPoint;//原始分double dSPoint;//标准分double dNum;//学分
}stScore;

  在StdAfx.h中添加下列头文件以支持CArray的使用:

#include <afxtempl.h>

至于位置,可以写这里:

#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions
#include <afxdisp.h>        // MFC Automation classes
#include <afxdtctl.h>        // MFC support for Internet Explorer 4 Common Controls
#include <afxtempl.h>
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>            // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT

  在GPACalculatorDlg.h的类GPACalculatorDlg的定义中添加私有对象arScore,用作分数存储:

CArray<stScore,stScore&> arScore;

  3.3 为类GPACalculatorDlg添加一些自定义功能函数(都是私有的。在类GPACalculatorDlg.h文件里添加函数声明,在类GPACalculatorDlg.cpp文件里添加函数实现):

  1>GetSDPoint:根据参比标准,将原始分转化为标准分。

double GetSDPoint(double dPoint);

double CGPACalculatorDlg::GetSDPoint(double dPoint){UpdateData();CArray<double,double&> arOPoint;CArray<double,double&> arSPoint;arOPoint.Add(m_dO1);arOPoint.Add(m_dO2);arOPoint.Add(m_dO3);arOPoint.Add(m_dO4);arOPoint.Add(m_dO5);arOPoint.Add(m_dO6);arOPoint.Add(m_dO7);arOPoint.Add(m_dO8);arSPoint.Add(m_dS1);arSPoint.Add(m_dS2);arSPoint.Add(m_dS3);arSPoint.Add(m_dS4);arSPoint.Add(m_dS5);arSPoint.Add(m_dS6);arSPoint.Add(m_dS7);if(dPoint>=arOPoint[0])return arSPoint[0];for(int i=1;i<arOPoint.GetSize();i++){if(dPoint>=arOPoint[i])return arSPoint[i-1];}return 0;
}

  2>SpliterString:分数文件是以“原始分 学分”的方式给出的,需要一个功能函数来将这个字符串拆分成两个double型的原始分和学分。

void SpliterString(CString str,double &a,double &b);

void CGPACalculatorDlg::SpliterString(CString str,double &a,double &b){CString strOne,strTwo;int ifind;str.TrimLeft(' ');str.TrimRight(' ');ifind=str.Find(' ');strOne=str.Left(ifind);strTwo=str.Right(str.GetLength()-ifind-1);a=atof(LPCTSTR(strOne));b=atof(LPCTSTR(strTwo));
}

  3>GatherData:将分数文件的信息导入到分数存储结构,当m_sPathName="",即无分数文件时,则导入失败。

void GatherData();

void CGPACalculatorDlg::GatherData(){CString str;stScore temp;if(m_sPathName=="")return;arScore.RemoveAll();CFile file(m_sPathName,CFile::modeRead);CArchive ar(&file,CArchive::load);;ar.ReadString(str);while(str!=""){SpliterString(str,temp.dOPoint,temp.dNum);temp.dSPoint=GetSDPoint(temp.dOPoint);arScore.Add(temp);ar.ReadString(str);}
}

  4>ChangeType:根据不同的输入值,转变成不同的参比标准。

void ChangeType(int nType);

void CGPACalculatorDlg::ChangeType(int nType){switch(nType){case 0:case 4:m_dS1=m_dS2=m_dS3=m_dS4=m_dS5=m_dS6=m_dS7=0;m_dO1=m_dO2=m_dO3=m_dO4=m_dO5=m_dO6=m_dO7=m_dO8=0;break;case 1:m_dS1=4;m_dS2=3;m_dS3=2;m_dS4=1;m_dS5=m_dS6=m_dS7=0;m_dO1=100;m_dO2=90;m_dO3=80;m_dO4=70;m_dO5=60;m_dO6=m_dO7=m_dO8=0;break;case 2:m_dS1=4.3;m_dS2=4;m_dS3=3.7;m_dS4=3.3;m_dS5=3.0;m_dS6=2.7;m_dS7=2.3;m_dO1=100;m_dO2=90;m_dO3=85;m_dO4=80;m_dO5=75;m_dO6=70;m_dO7=65;m_dO8=60;break;case 3:m_dS1=4;m_dS2=3;m_dS3=2;m_dS4=m_dS5=m_dS6=m_dS7=0;m_dO1=100;m_dO2=85;m_dO3=70;m_dO4=60;m_dO5=m_dO6=m_dO7=m_dO8=0;break;}
}

  5>SetEditRead:输入为TRUE时,参比标准的编辑框将被设为只读模式;而输入为FALSE时,参比标准的编辑框将被设为可写模式。

void SetEditRead(bool bReadOnly);

void CGPACalculatorDlg::SetEditRead(bool bReadOnly){((CEdit *)GetDlgItem(IDC_EDIT_S1))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_S2))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_S3))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_S4))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_S5))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_S6))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_S7))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_O1))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_O2))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_O3))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_O4))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_O5))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_O6))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_O7))->SetReadOnly(bReadOnly);((CEdit *)GetDlgItem(IDC_EDIT_O8))->SetReadOnly(bReadOnly);
}

  3.4 控件事件:借助ClassWizard添加控件对应的处理函数。

  1>组合框:可以通过下拉菜单选择不同的参比标准。

  需要做两步:

  首先,为组合框设初始值,否则下拉菜单里是空的。在CGPACalculatorDlg.cpp文件里的OnInitDialog()初始化函数里添加代码为组合框设初始值:

BOOL CGPACalculatorDlg::OnInitDialog()
{CDialog::OnInitDialog();// IDC_COMBO_STANDRDm_cmbStandard.AddString("0");m_cmbStandard.AddString("1");m_cmbStandard.AddString("2");m_cmbStandard.AddString("3");m_cmbStandard.AddString("用户自定义");// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);......

  然后,还需要为组合框添加处理函数:

void CGPACalculatorDlg::OnSelchangeComboStandard()
{// TODO: Add your control notification handler code hereint nIndex=m_cmbStandard.GetCurSel();if(4==nIndex)SetEditRead(false);elseSetEditRead(true);ChangeType(nIndex);UpdateData(false);
}

  2>【浏览...】按钮:弹出“打开”对话框以供选择磁盘上的分数文件。添加的处理函数如下:

void CGPACalculatorDlg::OnButtonOpen()
{// TODO: Add your control notification handler code hereCFileDialog fdlg(true,NULL,NULL,OFN_OVERWRITEPROMPT,"成绩文件|*.dat;*.txt|",NULL);if(fdlg.DoModal()==IDOK){m_sPathName=fdlg.GetPathName();}UpdateData(false);
}

  3>【统计】按钮:单击该按钮计算各项参数值,并把分数显示在列表框。添加的处理函数如下:

void CGPACalculatorDlg::OnButtonOk()
{// TODO: Add your control notification handler code heredouble dGPAall=0;double dAvgall=0;GatherData();int i=0;int size=arScore.GetSize();if(size==0)return;m_ListScore.ResetContent();m_ListScore.AddString("序号  成绩     学分    标准");m_ListScore.AddString("-------------------------------------------");m_dTotal=0;while(i<size){CString str;m_dTotal+=arScore.GetAt(i).dNum;dGPAall+=arScore.GetAt(i).dSPoint*arScore.GetAt(i).dNum;dAvgall+=arScore.GetAt(i).dOPoint*arScore.GetAt(i).dNum;str.Format("%.2d    %0.2f    %0.2f    %0.2f",i+1,arScore.GetAt(i).dOPoint,arScore.GetAt(i).dNum,arScore.GetAt(i).dSPoint);i++;m_ListScore.AddString(str);}m_strGPA.Format("%.2f",dGPAall/m_dTotal);m_strAverage.Format("%.2f",dAvgall/m_dTotal);UpdateData(false);
}

  3.5 界面外观

  若对界面控件默认的外观感到不满意,可以截取消息加以控制。本程序截取VM_CTLCOLOR消息来达到修改控件外观颜色的目的。操作如下:

处理函数为:

HBRUSH CGPACalculatorDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);// TODO: Change any attributes of the DC hereswitch(pWnd->GetDlgCtrlID()){case IDC_EDIT_S1:case IDC_EDIT_S2:case IDC_EDIT_S3:case IDC_EDIT_S4:case IDC_EDIT_S5:case IDC_EDIT_S6:case IDC_EDIT_S7:case IDC_EDIT_O1:case IDC_EDIT_O2:case IDC_EDIT_O3:case IDC_EDIT_O4:case IDC_EDIT_O5:case IDC_EDIT_O6:case IDC_EDIT_O7:case IDC_EDIT_O8:pDC->SetBkColor(RGB(255,255,255));pDC->SetTextColor(RGB(0,0,255));break;case IDC_LIST_SCORE:pDC->SetBkColor(RGB(255,255,255));pDC->SetTextColor(RGB(0,0,255));break;case IDC_EDIT_AVERAGE:case IDC_EDIT_GPA:case IDC_EDIT_TOTAL:pDC->SetBkColor(RGB(255,255,255));pDC->SetTextColor(RGB(255,0,255));}// TODO: Return a different brush if the default is not desiredreturn hbr;
}

五、运行结果:

  1.使用说明:

  1.1 GPA计算器要求文件输入,输入格式:[spaces]课程成绩<spaces>学分数[spaces]

  eg:

94 6.5
62 1.5
85 2.5
72 3
90 2
93 1.5
87 3
94 1.5

  1.2 GPA计算器提供了几种GPA参考分数标准,可通过下拉列表选择。若程序中提供的标准(0/1/2/3)不能满足需要的话,可选择“用户自定义”,可以自行在编辑框里填入自己所需的标准。

  1.3 选择分数文件和参比标准后,单击【统计】按钮即可求出相应的加权平均分、GPA及总学分等。程序会显示分数文件中的分数,可据此核对计算结果是否正确。

  2.程序演示:

六、小结

  麻雀虽小,五脏俱全。

转载于:https://www.cnblogs.com/jiu0821/p/4631484.html

第二个MFC实例:GPA计算器相关推荐

  1. 实例【GPA计算器】的制作过程之MFC初体验收获

    跟着书上的例子制作了一个GPA计算器.遇到并解决了如下几个问题. 1.运行程序后,combobox下拉箭头显示内容太少,必须通过点击箭头才能下拉选项.解决方案:在设计combobox时,点击" ...

  2. python计算gpa,Python版GPA计算器

    最近在网申投简历时遇到一个需要计算GPA的问题,想起自己在上学时写的Excel公式版GPA计算器略显low,而且操作也比较复杂,于是一时兴起,写了个Python版的,在此分享给大家! 准备工作: 用户 ...

  3. gpa计算器java代码_GP中的GPA计算器帮助

    我目前正在学习C,在章节结尾处的一个挑战问题是我 Build 了一个GPA计算器 . 这是挑战: 创建学生GPA平均计算器 . 该程序应提示用户输入最多30个GPA,这些GPA存储在一维数组中 . 每 ...

  4. java输出GPA,简单的C GPA计算器问题

    我正在尝试使用GradePoint()函数来创建GPA计算器来进行实际转换,将int main()用于cin和cout . 我被困了几个小时 . 我尝试了许多不同的东西,并查找了许多不同的教程,但似乎 ...

  5. java输出GPA_使用ENUM和switch case的循环Java GPA计算器

    更新: 现在我只需要修复它的循环和切换方法来获取用户输入的字母并将它们切换为用于计算gpa的数字. 上一条消息: 我正在尝试制作一个简单的gpa计算器,它已经有ENUM的课程,它只会询问用户的字母等级 ...

  6. 爬虫经典项目——HFUT GPA计算器

    前言 之前搭建完Python的环境之后就一直没有时间真正静下来写一个完整的爬虫应用程序,这几天实习的日子开始填坑,Python爬虫最经典的也比较有意义的就是GPA计算器了,它模拟了登录捕获教务系统中成 ...

  7. 使用JavaScript实现GPA计算器(学科实践任务 一)

    学科实践任务(一):GPA计算器 <!DOCTYPE html> <html><head><meta charset="utf-8"> ...

  8. 《吕鑫:VC++6.0就业培训宝典之MFC视频教程》学习笔记 -- 第二章 MFC原理介绍

    第二章 MFC原理介绍 2.1 第一个Win32软件 2.2 Win32对话框程序开发 2.3 程序资源管理和Windows数据类型 2.4 Win32环境下的多对话框管理 2.5 初步学习MFC软件 ...

  9. VC2019基于MFC对话框——加法计算器

    VC2019基于MFC对话框--加法计算器 目录 一.新建一个MFC项目 二.安装控件 三.为按钮等控件添加消息函数 四.运行 一.新建一个MFC项目 创建项目谁都会哈,这就不赘述了. 这里说一个我在 ...

最新文章

  1. -变量,进制,数据类型,标识符
  2. 强化学习之父--David Sliver最新演讲内容!
  3. VTK修炼之道7_三维场景基本要素:光照
  4. 调试九法:软硬件错误的排查之道书评
  5. 浅谈同城双中心的网络部署模型
  6. linux 学习操作小计
  7. VMware NSX part 1(介绍) part 2(NSX-Manager安装) part 3(NSX Controller部署)
  8. 第6章 类型和成员基础
  9. js中addEventListener第三个参数涉及到的事件捕获与冒泡
  10. GCC的gcc和g++区别,本质而言,gcc和g++并不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中要编译的文件的类型,调用对应的GUN编译器而已
  11. editplus使用php,EditPlus配置PHP调试环境详细图文介绍
  12. java怎么解析mdb文件_java解析MDB文件的方法,已经写成公用方法
  13. 项目,项目集与项目组合的关系
  14. 【功能测试】part1
  15. arcmap中有火星坐标码_GIS转换之火星坐标系转换
  16. NFT+体育,卡塔尔世界杯有哪些NFT看点!
  17. Smartbi报表工具实现并查询(不去重)
  18. [31期]上班这点事
  19. ToDesk for Mac v4.2.1 中文版 远程控制软件
  20. 2013年最后2个月的学习目标(成果)(上次更新2013年11月18日)

热门文章

  1. 券商接口量化交易策略——KDJ指标
  2. IDEA 集成git
  3. 打造前端 Deepin Linux 工作环境——安装系统
  4. Python的特点及数据的存储单位(¥4)
  5. 51单片机PCF8591-AD-DA转换
  6. Matlab使用Usrp进行数据收发
  7. 负数的二进制表示及左移功能的验证
  8. 【Paper】毕业论文免费查重网站平台汇总
  9. NRC 0x78 在CAPL中如何打开和关闭
  10. 【大学物理·静止电荷的电场】静电场 电场强度