MFC计算器课程设计报告
计算机应用3班黄锦湫,罗洁,饶益
指导老师:蒋鹏
2009.3.15
一.题目:利用MFC框架编写简易计算器
要求使用MFC框架在Visual Studio 6.0环境下编写一个简易的计算器,支持任意位数的加减乘数,正负转换,并且实现BackSpace CE C功能。
二.设计过程
1. Windows消息处理机制的理解
首先编写程序需要对Windows程序的消息处理机制(Message Handle)有个比较清晰的了解。Windows的程序都是通过消息来传送数据,有不需要用户参与的系统消息,比如异常处理等。还有用户消息,比如鼠标的单击,双击,键盘的键入等。
2. 界面的设计
仿照Windows附件里面的计算器,在资源视图中画好界面,如图:
主要使用到Layout菜单中的Align功能对各个按钮进行对其,使界面更加整洁。拖出的控件有上面的一个Edit控件用于显示数字,Button控件用于处理鼠标的消息。
3. 建立的变量,控件的命名,对应的消息处理函数对应表
变量定义:
double poz; //保存小数点的位置,初始化为1,表示poz-1个小数点。
double m_Dis; //Edit控件上需要显示的数字
BOOL point_flag; //小数点表示位,判定是否是小数,是小数为1,不是小数为0。
double numfirst; //保存计算过程中的前一个数字,
double numsecond;//保存计算过程中的第二个数字
char op;//记录当前的计算符号,可以为’+’,’-’,’*’,’/’,’=’,’c’,’n’
变量初始化:
poz=1;
m_Dis = 0.0;
numfirst=0;
numsecond=0;
op=0;
4. 设计思路
a) 首先考虑对所有按键分为两类,数字类和符号类,0,1,2,3,4,5,6,7,8,9为数字类,+,-,*,/,=为符号类。数字在计算的过程中最多需要保存两个,所以定义了两个double型变量numfirst和numsecond来进行存储。符号需要一个char op来存储。
b) 然后考虑在计算的过程中,numfirst和numsecond的存储状态有三种,一种是numfirst==0 && numsecond==0 也就是程序刚开始运行还没有开始录入数字的状态。二种是numfirst!=0 && numsecond==0 也就是第一个数字已经录入,符号也已经录入时候把m_Dis的值直接赋值给numfirst,第三种是numfirst!=0 &&numsecond!=0,表示可以通过op来把两数合并为一个数。
c) 考虑到该计算器支持连续的计算,比如3.33+1.33*88/96= ?。所以必须在点符号Button也要计算出之前的结果,通过判断op,来计算,把两个数字合并为一个数字,方便下一次运算,功能近似于点=,所以把=也划分到符号类。
d) 因为数字全部使用的是double,键入的数字必须通过一定的处理达到累加的效果,加上小数和整数的处理差异性大,所以分别用point_flag来判断,分别出来小数和整数。
5. 成员函数及其释义
因为对OnNum0()到OnNum9()的处理函数差异仅在一个数字上,可以通过调用一个共同的函数OnCal(double num)来简化源代码长度,增加模块性。
void CCalcDlg::OnCal(double num)
{ //分三种状态来处理
if(numfirst!=0 && numsecond!=0)
{
if(point_flag==TRUE) //判定为小数
{
poz*=0.1; //小数进位
m_Dis=m_Dis+poz*num;//递增
UpdateData(false); //把结果从内存传递到屏幕
}
else
{
m_Dis=m_Dis*10+num;
UpdateData(false);
}
}
if(numfirst!=0 && numsecond==0)
{
if(point_flag==TRUE)
{
poz*=0.1;
m_Dis=m_Dis+poz*num;
UpdateData(false);
}
else//判定为整数
{
m_Dis=m_Dis*10+num;//递增
UpdateData(false);
}
}
if(numfirst==0 && numsecond==0)
{
if(point_flag==TRUE)
{
poz*=0.1;
m_Dis=m_Dis+poz*num;
UpdateData(false);
}
else
{
m_Dis=m_Dis*10+num;
UpdateData(false);
}
}
}
以OnAdd()为例子讲解符号的处理函数,函数的功能是先判定之前按下字符时op的值,更具op的值来进行相应的运算。
void CCalcDlg::OnAdd()
{ //根据numfirst和numsecond和op的值分为5种状态。
if(numfirst!=0 && numsecond==0&&op=='+')
{
numsecond=m_Dis;
numfirst=numfirst+numsecond; //之前按的是加把两个数赋值到前一个数
m_Dis=numfirst;//赋值给屏幕
numsecond=0; //从新赋值为0,清空,不影响下一次判断
UpdateData(FALSE);
m_Dis=0; //屏幕的值同时清空
}
if(numfirst!=0 && numsecond==0&&op=='-')
{
numsecond=m_Dis;
numfirst=numfirst-numsecond;
m_Dis=numfirst;
numsecond=0;
UpdateData(FALSE);
m_Dis=0;
}
if(numfirst!=0 && numsecond==0&&op=='*')
{
numsecond=m_Dis;
numfirst=numfirst*numsecond;
m_Dis=numfirst;
numsecond=0;
UpdateData(FALSE);
m_Dis=0;
}
if(numfirst!=0 && numsecond==0&&op=='/')
{
numsecond=m_Dis;
numfirst=numfirst/numsecond;
m_Dis=numfirst;
numsecond=0;
UpdateData(FALSE);
m_Dis=0;
}
if(numfirst==0 && numsecond==0)
{ //该状态为程序启动还没有开始录入输入的状态
numfirst=m_Dis; //屏幕的值赋值到numfirst
UpdateData(FALSE);
m_Dis=0;
}
op='+'; //最后记录最后一个操作是+
poz=1;//小数点位置归位
point_flag=FALSE;//默认小数点标志为整数,也就是0,也就是FALSE
}
“+/-“按钮的处理函数
void CCalcDlg::OnNeg()
{
m_Dis=-m_Dis;//换个符号,其他都一样
UpdateData(FALSE);
poz=1;
point_flag=FALSE;
}
‘.’按钮的处理函数
void CCalcDlg::OnPt()
{
point_flag=TRUE; //把标志位改为“小数点”状态
}
“Backspace”按钮的处理
void CCalcDlg::OnBackspace()
{
//主要通过_gcvt()和strtod()函数进行字符串和浮点数之间的转换
char buffer[30]; //定义个装字符的数组
_gcvt(m_Dis,sizeof(m_Dis),buffer); //把m_Dis存的数字转换为string
for(int i=0;i<30;i++)
{
if(buffer[i]=='.'&& buffer[i+1]==0)//判断是否为整数
{
point_flag=FALSE; //标志位设置为“整数位”
break;
}
}
if(point_flag==TRUE) //如果是小数
{
for(int j=0;j<30;j++)
{
if(buffer[j]==0)
{
buffer[j-1]=0; //把’\0’之前的字符赋值为’\0’,就相当于剪掉最后一位
break;
}
}
}
else //如果是整数
{
buffer[i-1]=0; //剪掉’.’之前那位
}
m_Dis=strtod(buffer,NULL);//再用strtod弄成浮点数
UpdateData(FALSE);
poz=1;
}
‘CE’按钮处理函数
void CCalcDlg::OnCe()
{
if(numfirst!=0 && numsecond==0)//CE只能修改第二个数字
{
m_Dis=0; //把屏幕的值赋值为0
UpdateData(FALSE);//并显示出来
}
}
‘C’按钮处理函数
void CCalcDlg::OnClear()
{
op=NULL; //清空符号
numfirst=0;//清空第一个数字
numsecond=0;//清空第二个数字
point_flag=FALSE;//改为默认整数位
poz=1;//小数点归位
m_Dis=0;
UpdateData(FALSE); //屏幕显示归0
}
键盘响应:
void CCalcDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch(nChar)
{
case VK_NUMPAD0:
OnNum0();break;
case VK_NUMPAD1:
OnNum1();break;
case VK_NUMPAD2:
OnNum2();break;
case VK_NUMPAD3:
OnNum3();break;
case VK_NUMPAD4:
OnNum4();break;
case VK_NUMPAD5:
OnNum5();break;
case VK_NUMPAD6:
OnNum6();break;
case VK_NUMPAD7:
OnNum7();break;
case VK_NUMPAD8:
OnNum8();break;
case VK_NUMPAD9:
OnNum9();break;
case VK_ADD:
OnAdd();break;
case VK_SUBTRACT:
OnMin();break;
case VK_MULTIPLY:
OnMul();break;
case VK_DIVIDE:
OnDiv();break;
case VK_BACK:
OnBackspace();break;
case VK_DECIMAL:
OnPt();break;
case VK_DELETE:
OnBackspace();break;
case VK_RETURN:
OnEqu();break;
}
CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}
BOOL CCalcDlg::PreTranslateMessage(MSG* pMsg)
{
SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);
return CDialog::PreTranslateMessage(pMsg);
}
总结:
本次MFC计算器的制作,学习到了MFC基本的编程方法,增加了小组开发的团结协作能力。对OOP编程的理解进一步加深。但是程序仍然没存在一定的问题,比如除数不能为0的Exception handle,符号键多次点击结果混乱。由于时间仓促,如果有更多的时间,必定这些问题会迎刃而解。通过这次课程设计,以后Windows 应用程序势必会轻车熟路。
一、设计目标与内容
1. 了解Windows编程的基础知识,掌握MFC应用程序的基本知识;
2. 基本掌握面向对象程序设计的基本思路和方法;
3. 掌握用VC++开发应用程序的的一般步骤和方法;
4. 能够利用所学的基本知识,设计一个简单的计算器应用程序,实现基本的加、减、乘、除、求平方根,求倒数等基本运算(必须实现的功能),实现求角度的正弦、余弦、正切等基本运算、实现求指数、自然对数、常用对数等基本运算(这部分功能选做)。
5. 在程序中注意处理数据和运算符的输入,计算结果的显示。
二,设计要求
1. 用VC++进行编码,实现应用程序的功能。注重编码质量,代码要有适当的注释;
2. 提交设计报告一份(课程设计任务书、目录、设计的基本思路、设计的步骤及主要代码、心得体会、参考文献)。
能够利用所学的基本知识,设计一个简单的计算器应用程序,实现基本的加、减、乘、除、求平方根,求倒数等基本运算(必须实现的功能),实现求角度的正弦、余弦、正切等基本运算、实现求指数、自然对数、常用对数等基本运算(这部分功能选做)。在程序中注意处理数据和运算符的输入,计算结果的显示。
u 新建工程Counter
新建工程,选择对话框应用程序。
u 程序运行主界面
图2-1
在对话框内添加相应的控件,分别给编辑框添加三个变量m_N1,m_N2和m_Result。
然后添加一个组合框,在里面添加十二个单选按钮设置第一个单选按钮为组,如图
图2-2
然后给对话框类添加一个int变量Operator用来作相应运算时的标记。
u 给控件添加相应的函数
1、给单选按钮添加相应的函数
void CCounterDlg::OnRadio1()
{
Operator=1;
}
void CCounterDlg::OnRadio2()
{
Operator=2;
}
void CCounterDlg::OnRadio3()
{
Operator=3;
}
void CCounterDlg::OnRadio4()
{
Operator=4;
}
void CCounterDlg::OnRadio5()
{
Operator=5;
}
void CCounterDlg::OnRadio6()
{
Operator=6;
}
void CCounterDlg::OnRadio7()
{
Operator=7;
}
void CCounterDlg::OnRadio8()
{
Operator=8;
}
void CCounterDlg::OnRadio9()
{
Operator=9;
}
void CCounterDlg::OnRadio10()
{
Operator=10;
}
void CCounterDlg::OnRadio11()
{
Operator=11;
}
void CCounterDlg::OnRadio12()
{
Operator=12;
}
用来作相应的操作时标记Operator的值。
2、给Button1(计算)添加相应的函数
void CCounterDlg::OnButton1()
{
UpdateData();
double i=0,j=1;
switch(Operator)
{
case 1:
m_Result=m_N1+m_N2;break;
case 2:
m_Result=m_N1-m_N2;break;
case 3:
m_Result=m_N1*m_N2;break;
case 4:
if(m_N2==0)
MessageBox("除数不能为零!");
else
{
m_Result=m_N1/m_N2;break;
}
case 5:
if(m_N1==0)
MessageBox("分母不能为零!");
else
{
m_Result=1/m_N1;break;
}
case 6:
if(m_N2==0)
m_Result=1;
else
{
for(i=0;i<m_N2;i++)
j=j*m_N1;
m_Result=j;
}break;
case 7:
m_Result=pow(m_N1,1/m_N2);break;
case 8:
m_Result=sin(m_N1);break;
case 9:
m_Result=cos(m_N1);break;
case 10:
m_Result=tan(m_N1);break;
case 11:
m_Result=log(m_N1);break;
case 12:
if(m_N1<0)
MessageBox("对数取值范围大于零!");
else
{
m_Result=log10(m_N1);break;
}
}
UpdateData(FALSE);
}
3、给Button2(清零)添加相应的函数
void CCounterDlg::OnButton2()
{
UpdateData();
m_N1=0;
m_N2=0;
m_Result=0;
UpdateData(FALSE);
}
4、给Button3(退出)添加相应的函数
void CCounterDlg::OnButton3()
{
CDialog::OnOK();
}
u 编译运行
计算器是一个比较简单的程序,里面的很多运算我们只需要调用C++的相应函数就行了,所以做起来很容易,但是如果要想做一个比较复杂的计算器就需要我们下一定的功夫了。
华东交通大学课程设计华东交通大学课程设计课程设计题目计算器设计课程题目年级专业学号姓名组员指导教师Java程序设计信息一班1华东交…
计算机综合课程设计报告小组编号06课题名称趣味贪吃蛇小组成员20xx年10月计算机综合课程设计报告目录目录11项目背景112系统目…
MFC计算器课程设计报告计算机应用3班黄锦湫罗洁饶益指导老师蒋鹏20xx315一题目利用MFC框架编写简易计算器要求使用MFC框架…
计算机网络课程设计报告一.课程设计的题目、目的及要求.......................................…
武汉理工大学专业课程设计2课程设计说明书目录1基本功能描述12设计思路13软件设计431设计步骤44结论与心得体会127附设计中的…
计算机科学与工程学院项目报告设计名称Windows程序设计综合项目设计题目学生学号专业班级学生姓名xxxxxxxx学生成绩指导教师…
华北科技学院课程设计说明书班级姓名设计题目设计时间指导教师评语评阅成绩评阅教师华北科技学院课程设计说明书目录第1章绪论111选题的…
河海大学计算机及信息工程学院常州MFC课程设计报告题目聊天室程序设计学号20xx2325专业计算机科学与技术授课班号243002学…
中南大学本科生课程设计(实践)任务书、设计报告(C++语言程序设计)题目:统计稿件管理数据程序设计计算机基础教学实验中心20##年…
山东中医药大学理工学院课程设计报告课程名称高级语言课程设计课程代码07300561设计内容汉诺塔演示系统二0一二年12月21日1目…