mfc基于对话框计算器程序

时间:2022-05-12 22:57:00

计算器程序

mfc基于对话框计算器程序

计算器程序有一个难点便是用户不同的使用习惯,这也是我们开始写程序之前需要想清楚的。
举个例子:

4+3-1=?

就这个普通的三数运算而言,用户不同的输入方式就有多种。

  • 直接依次输入:4 → + → 3 → — → 1 → =
    在减号被按下时,4+3的结果已经显示出来了
  • 先输入:4 → + → 3 → =
    再输入:- → 1 → =
    在该操作中我们可以看出计算的结果也是需要被我们用来计算的

还有几个需要注意的问题:

  • 当直接按下小数点,我们应默认为“0.”,帮助用户自动补全
  • 按了一个运算符之后又按下了一个运算符,我们应覆盖前一个运算符
  • 结果为整数的时候我们显示整数,结果为小数我们应保留一定小数位
  • “AC”用来清屏,开始新的计算
  • 除数为零时提示错误

下面开始我们的程序编写

  1. 在VS中新建项目→MFC应用程序→基于对话框→完成(这里我将项目名称默认为calculator,项目的名字会影响默认文件的名字)。
  2. 把给定的对话框中的控件都Delete,然后我们来绘制界面,按键用Button绘制,显示区域用Edit Control绘制,最上面的“CALCULATOR”用Static Text绘制。
  3. 给绘制好的控件都起一个语义化的ID(不是必要的,但是可以让我们接下来编写代码时更清楚),我的数字1是“IDC_BUTTON_NUM1”,然后改变他们的Caption值(就是控件上显示的内容)。
  4. 需要注意的是Edit Control的属性中,外观中的Align Text应该选择Right(想想我们真实计算器的显示屏),行为中的Read Only选择True(这个文本编辑框我们只是用来显示的,所以是只读的),最上方的Static Text文字也要设置为居中的。
  5. 直接双击控件就可以进入代码编辑区域了

mfc基于对话框计算器程序


代码部分

经过上面的过程你可能会发现,文本编辑框中的文字太小了,静态文本中的文字也是,那么我们先去改变其字体大小,在“calculatorDlg.cpp”文件中的“OnInitDialog()”中添加下面这段代码,不具体讲都是什么意思了,也是我百度来的方法,有基础的应该就能看懂。


    CFont *m_Font;
    m_Font = new CFont;
    m_Font->CreateFont(50,20,0,0,100,
        FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_SWISS,L"Arial");
    CEdit *m_Edit=(CEdit *)GetDlgItem(IDC_EDIT1);
    m_Edit->SetFont(m_Font,FALSE);
    GetDlgItem(IDC_EDIT1)->SetFont(m_Font);
    GetDlgItem(IDC_STATIC)->SetFont(m_Font);

但是运行程序发现按下数字键并不能使文本框显示出数字,是的,我们还没有对按键和文本输入框之间进行绑定。
基本思路就是我们为文本编辑框添加一个变量(变量名为“mmm”),方法是右键该文本框 → 添加变量,类别选择为Value,变量类型默认为CString。然后我们在数字按键中改变这个变量,UpdateData(FALSE)更新文本编辑器,就能实现显示数字了。代码如下。


void CcalculatorDlg::OnBnClickedButtonNum1()
{
    // TODO: 在此添加控件通知处理程序代码
    if(m_p==1)
    mmm='0';
    if (mmm!='0')
    {
        mmm+='1';
        m_p=2;
    }
    else
    {
        mmm='1'; 
        m_p=2;
    }
        UpdateData(FALSE); 
}
//暂且不管m_p的用法

UpdateData()这个函数是用来实现不同控件之间更新数据的,FALSE及TRUE控制方向。

完成了绑定,我们就要想想怎么实现计算过程了。通过前面计算器的分析,我们显然可以知道,我们最少需要三个变量:储存单次运算中两数的值及其运算结果。但只有这三个还远远无法实现“计算”这个基本功能,我们还要有储存运算符的变量,实际上我们会在程序的编写过程中为了实现某些特定的功能而回过头来添加这些变量,为了方便,先全部列举出来。变量的定义在“calculatorDlg.h”文件中。然后在cpp文件中的构造函数中进行初始化。

  • m_ num1,m_ num2 用来存储要运算的两数值
  • m_ action 用来存储运算符(默认为0,1为+,2为-,etc)
  • m_ preaction 用来存储上一次的运算符
  • m_ p 用来判定是否是以结果为起始数继续运算
    当按下“=”完成运算,再按下数字或运算符是有区别的(参照真实的计算器)
    其实这个变量还有几处妙用,在一开始我没有添加这个变量的时候,计算器也能正常运行,但在计算的过程中需频繁的使用“AC”,表现的不是那么“智能”,很多地方的细节处理的不到位,我总觉得少了点什么,试着添加一些变量但越加越多,最后我把这些变量整合成了一个,用来记录运算过程进行到了哪个阶段!
  • m_q 用来判定除数是否为零
    为了代码的简洁易读,我将计算方法写在了一个函数中,通过按钮中调用这个函数来实现计算。(同样,在.h文件中定义该函数,在cpp文件中写函数内容)
    这里我们必须弄清楚MFC中数据转换的方法:

  • string → double :_tstof(CString);

  • double → string :CString.Format(_T(“%.xf”),double);(x为保留的小数位数)

因为文本编辑框中的内容是CString类型的,我们无法直接用来计算,而我们也只有给它CString类型的数据它才能显示出来,计算函数内容如下。


void CcalculatorDlg::cal(int action)
{
    m_num2=mmm;
    double num1,num2;
    double num=0;
    num1=_tstof(m_num1);
    num2=_tstof(m_num2);
    switch(action)
    {
    case 1:
        num=num1+num2;
        break;
    case 2:
        num=num1-num2;
        break;
    case 3:
        num=num1*num2;
        break;
    case 4:
        if(num2==0)
        {
            mmm="除数不能为0";
            m_q=1;
        }
        else
        num=num1/num2;
        break; 
    default:break;
    }
    if(m_q==1)
    {
        UpdateData(FALSE);
    }
    else
    {
    if(num-(int)num==0)
        mmm.Format(_T("%.0f"),num);
    else
        mmm.Format(_T("%.2f"),num); 
    UpdateData(FALSE);
    }
    m_preaction=0; 
}

基本上关键的部分都完成了,把各个部分代码都选一个贴出来(同一类的控件函数内容大致相同),其中“0”以及“.”有很大不同,可以体会一下m_p在其中的作用。

“.”


void CcalculatorDlg::OnBnClickedButtonPoint()
{
    // TODO: 在此添加控件通知处理程序代码
    if (mmm!='0')
    {
        mmm+='.';
        if(m_p==1)
        {
            mmm="0.";
            m_p=2;
        }
    }
    else
    {
        mmm="0.";
        m_p=2;
    }
    UpdateData(FALSE);
}

“0”


void CcalculatorDlg::OnBnClickedButtonNum0()
{
    // TODO: 在此添加控件通知处理程序代码
    if(m_p==1)
        mmm='0';

    if (mmm!='0')
        mmm+='0';
    else
        mmm='0'; 
    UpdateData(FALSE); 
}

“+”


void CcalculatorDlg::OnBnClickedButtonadd()
{
    // TODO: 在此添加控件通知处理程序代码
    if (m_preaction)   
    {
        m_num2=mmm; 
        cal(m_action);
    }
    m_action=1;
    m_preaction=m_action;
    m_num1=mmm;
    mmm='0';   
}

“=”


void CcalculatorDlg::OnBnClickedButton16()//=
{
    // TODO: 在此添加控件通知处理程序代码
    cal(m_action);
    m_p=1;
}

“AC”


void CcalculatorDlg::OnBnClickedButtonac()
{
    // TODO: 在此添加控件通知处理程序代码
    mmm='0';
    m_action=0;
    m_preaction=0;
    UpdateData(FALSE);
}