MFC计算器编程设计报告.docx
《MFC计算器编程设计报告.docx》由会员分享,可在线阅读,更多相关《MFC计算器编程设计报告.docx(31页珍藏版)》请在冰豆网上搜索。
MFC计算器编程设计报告
MFC计算器课程设计报告
地信091
指导老师:
2010.11.15
一.题目:
利用MFC框架编写简易计算器
要求使用MFC框架在VisualStudio6.0环境下编写一个简易的计算器,支持任意位数的加减乘数,正负转换,并且实现BackSpaceCEC功能。
二.设计过程
1.Windows消息处理机制的理解
首先编写程序需要对Windows程序的消息处理机制(MessageHandle)有个比较清晰的了解。
Windows的程序都是通过消息来传送数据,有不需要用户参与的系统消息,比如异常处理等。
还有用户消息,比如鼠标的单击,双击,键盘的键入等。
2.界面的设计
仿照Windows附件里面的计算器,在资源视图中画好界面,如图:
主要使用到Layout菜单中的Align功能对各个按钮进行对其,使界面更加整洁。
拖出的控件有上面的一个Edit控件用于显示数字,Button控件用于处理鼠标的消息。
3.建立的变量,控件的命名,对应的消息处理函数对应表
ID
CAPTION
MessageHandler
IDD_CALC_DIALOG
简易计算器1.0Beta1版
N/A
IDC_NUM0
0
OnNum0
IDC_NUM1
1
OnNum1
IDC_NUM2
2
OnNum2
IDC_NUM3
3
OnNum3
IDC_NUM4
4
OnNum4
IDC_NUM5
5
OnNum5
IDC_NUM6
6
OnNum6
IDC_NUM7
7
OnNum7
IDC_NUM8
8
OnNum8
IDC_NUM9
9
OnNum9
IDC_NEG
+/-
OnNeg
IDC_PT
.
OnPt
IDC_DIV
/
OnDiv
IDC_MUL
*
OnMul
IDC_MIN
-
OnMin
IDC_ADD
+
OnAdd
IDC_BACKSPACE
BACK
OnBackspace
IDC_CE
CE
OnCe
IDC_CLEAR
C
OnClear
IDC_EQU
=
OnEqu
IDC_DIS
N/A
N/A
OnCal(doublenum)
变量定义:
doublepoz;//保存小数点的位置,初始化为1,表示poz-1个小数点。
doublem_Dis;//Edit控件上需要显示的数字
BOOLpoint_flag;//小数点表示位,判定是否是小数,是小数为1,不是小数为0。
doublenumfirst;//保存计算过程中的前一个数字,
doublenumsecond;//保存计算过程中的第二个数字
charop;//记录当前的计算符号,可以为’+’,’-’,’*’,’/’,’=’,’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来进行存储。
符号需要一个charop来存储。
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(doublenum)来简化源代码长度,增加模块性。
voidCCalcDlg:
:
OnCal(doublenum)
{//分三种状态来处理
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的值来进行相应的运算。
voidCCalcDlg:
:
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
}
“+/-“按钮的处理函数
voidCCalcDlg:
:
OnNeg()
{
m_Dis=-m_Dis;//换个符号,其他都一样
UpdateData(FALSE);
poz=1;
point_flag=FALSE;
}
‘.’按钮的处理函数
voidCCalcDlg:
:
OnPt()
{
point_flag=TRUE;//把标志位改为“小数点”状态
}
“Backspace”按钮的处理
voidCCalcDlg:
:
OnBackspace()
{
//主要通过_gcvt()和strtod()函数进行字符串和浮点数之间的转换
charbuffer[30];//定义个装字符的数组
_gcvt(m_Dis,sizeof(m_Dis),buffer);//把m_Dis存的数字转换为string
for(inti=0;i<30;i++)
{
if(buffer[i]=='.'&&buffer[i+1]==0)//判断是否为整数
{
point_flag=FALSE;//标志位设置为“整数位”
break;
}
}
if(point_flag==TRUE)//如果是小数
{
for(intj=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’按钮处理函数
voidCCalcDlg:
:
OnCe()
{
if(numfirst!
=0&&numsecond==0)//CE只能修改第二个数字
{
m_Dis=0;//把屏幕的值赋值为0
UpdateData(FALSE);//并显示出来
}
}
‘C’按钮处理函数
voidCCalcDlg:
:
OnClear()
{
op=NULL;//清空符号
numfirst=0;//清空第一个数字
numsecond=0;//清空第二个数字
point_flag=FALSE;//改为默认整数位
poz=1;//小数点归位
m_Dis=0;
UpdateData(FALSE);//屏幕显示归0
}
键盘响应:
voidCCalcDlg:
:
OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags)
{
switch(nChar)
{
caseVK_NUMPAD0:
OnNum0();break;
caseVK_NUMPAD1:
OnNum1();break;
caseVK_NUMPAD2:
OnNum2();break;
caseVK_NUMPAD3:
OnNum3();break;
caseVK_NUMPAD4:
OnNum4();break;
caseVK_NUMPAD5:
OnNum5();break;
caseVK_NUMPAD6:
OnNum6();break;
caseVK_NUMPAD7:
OnNum7();break;
caseVK_NUMPAD8:
OnNum8();break;
caseVK_NUMPAD9:
OnNum9();break;
caseVK_ADD:
OnAdd();break;
caseVK_SUBTRACT:
OnMin();break;
caseVK_MULTIPLY:
OnMul();break;
caseVK_DIVIDE:
OnDiv();break;
caseVK_BACK:
OnBackspace();break;
caseVK_DECIMAL:
OnPt();break;
caseVK_DELETE:
OnBackspace();break;
caseVK_RETURN:
OnEqu();break;
}
CDialog:
:
OnKeyDown(nChar,nRepCnt,nFlags);
}
BOOLCCalcDlg:
:
PreTranslateMessage(MSG*pMsg)
{
SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);
returnCDialog:
:
PreTranslateMessage(pMsg);
}
//CalculatorDlg.cpp:
implementationfile
//
#include"stdafx.h"
#include"Calculator.h"
#include"CalculatorDlg.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CAboutDlgdialogusedforAppAbout
classCAboutDlg:
publicCDialog
{
public:
CAboutDlg();
//DialogData
//{{AFX_DATA(CAboutDlg)
enum{IDD=IDD_ABOUTBOX};
//}}AFX_DATA
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport
//}}AFX_VIRTUAL
//Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg:
:
CAboutDlg():
CDialog(CAboutDlg:
:
IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
voidCAboutDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//Nomessagehandlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CCalculatorDlgdialog
CCalculatorDlg:
:
CCalculatorDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CCalculatorDlg:
:
IDD,pParent)
{
//{{AFX_DATA_INIT(CCalculatorDlg)
poz=1;
numfirst=0;
numsecond=0;
op=0;
m_Dis=0.0;
//num=0;
//}}AFX_DATA_INIT
//NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCCalculatorDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCalculatorDlg)
DDX_Text(pDX,IDC_EDIT,m_Dis);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCalculatorDlg,CDialog)
//{{AFX_MSG_MAP(CCalculatorDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_NUM0,OnNum0)
ON_BN_CLICKED(IDC_NUM1,OnNum1)
ON_BN_CLICKED(IDC_NUM2,OnNum2)
ON_BN_CLICKED(IDC_NUM3,OnNum3)
ON_BN_CLICKED(IDC_NUM4,OnNum4)
ON_BN_CLICKED(IDC_NUM5,OnNum5)
ON_BN_CLICKED(IDC_NUM6,OnNum6)
ON_BN_CLICKED(IDC_NUM7,OnNum7)
ON_BN_CLICKED(IDC_NUM8,OnNum8)
ON_BN_CLICKED(IDC_NUM9,OnNum9)
ON_BN_CLICKED(IDC_ADD,OnAdd)
ON_BN_CLICKED(IDC_NEG,OnNeg)
ON_BN_CLICKED(IDC_PT,OnPt)
ON_BN_CLICKED(IDC_BACKSPACE,OnBackspace)
ON_BN_CLICKED(IDC_CE,OnCe)
ON_BN_CLICKED(IDC_CLEAR,OnClear)
ON_BN_CLICKED(IDC_MIN,OnMin)
ON_BN_CLICKED(IDC_MUL,OnMul)
ON_BN_CLICKED(IDC_DIV,OnDiv)
ON_BN_CLICKED(IDC_EOU,OnEou)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CCalculatorDlgmessagehandlers
BOOLCCalculatorDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
//Add"About..."menuitemtosystemmenu.
//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
//TODO:
Addextrainitializationhere
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
voidCCalculatorDlg:
:
OnSysCommand(UINTnID,LPARAMlParam)
{
if((nID&0xFFF0)==IDM_ABOUTBOX)
{
CAboutDlgdlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog:
:
OnSysCommand(nID,lParam);
}
}
//Ifyouaddaminimizebuttontoyourdialog,youwillneedthecodebelow
//todrawtheicon.ForMFCapplicationsusingthedocument/