计算器

MFC学习(六)计算器

1 stdafx.h 

  所谓头文件预编译,就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。

        预编译头文件通过编译stdafx.cpp生成,以工程名命名,由于预编译的头文件的后缀是“pch”,所以编译结果文件是projectname.pch。

        编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h这个头文件名是可以在project的编译设置里指定的。编译器认为,所有在指令#include "stdafx.h"前的代码都是预编译的,它跳过#include "stdafx. h"指令,使用projectname.pch编译这条指令之后的所有代码。

  因此,所有的MFC实现文件第一条语句都是:#include "stdafx.h"。在它前面的所有代码将被忽略,所以其他的头文件应该在这一行后面被包含。否则,你将会得到“No such file or directory”这样让你百思不得其解的错误提示。

  Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编译程序也要花费相当长的时间来完成工作。由于每个.CPP文件都包含相同的include文件,为每个.CPP文件都重复处理这些文件就显得很傻了。

为避免这种浪费,AppWizard和VisualC++编译程序一起进行工作,如下所示:

◎AppWizard建立了文件stdafx.h,该文件包含了所有当前工程文件需要的MFC include文件。且这一文件可以随被选择的选项而变化。

◎AppWizard然后就建立Stdafx.cpp。这个文件通常都是一样的。

◎然后AppWizard就建立起工程文件,这样第一个被编译的文件就是stdafx.cpp。

◎当VisualC++编译stdafx.cpp文件时,它将结果保存在一个名为stdafx.pch的文件里。(扩展名pch表示预编译头文件。)

◎当VisualC++编译随后的每个.cpp文件时,它阅读并使用它刚生成的.pch文件。VisualC++不再分析Windows include文件,除非你又编辑了stdafx.cpp或stdafx.h。

在这个过程中你必须遵守以下规则:

◎你编写的任何.cpp文件都必须首先包含stdafx.h。

◎如果你有工程文件里的大多数.cpp文件需要.h文件,顺便将它们加在stdafx.h(后部)上,然后预编译stdafx.cpp。

◎由于.pch文件具有大量的符号信息,它是你的工程文件里最大的文件。

如果你的磁盘空间有限,你就希望能将这个你从没使用过的工程文件中的.pch文件删除。执行程序时并不需要它们,且随着工程文件的重新建立,它们也自动地重新建立。

2 resource.h

是各种控件的ID的定义,在.rc文件中引用。  

3 Calculator.h

CCalculatorApp,继承自CWinApp的应用程序. 在Calculator.cpp中是全局定义:

CCalculatorApp theApp

在Calculator.h中,有声明 extern CCalculatorApp theApp; 这样所有包含了calculator.h的文件,都可以引用了。

CCalculatorApp :: InitInstance()是MFC程序的入口程序。

DECLARE_MESSAGE_MAP:是一个宏。作用是向类中添加消息映射必要的结构体和函数声明,只需要添加一次,放在什么位置并不重要,就如同类里其他普通函数的声明可以相互交换顺序一样。

只要当前类是CCmdTarget派生的,则必须提供消息映射以处理消息。

     具体方式是在类或者结构体末尾添加DECLARE_MESSAGE_MAP(无分号),然后在定义类成员函数的.CPP文件中,使用BEGIN_MESSAGE_MAP()宏和 END_MESSAGE_MAP()宏来实现对消息的处理。

       其中BEGIN_MESSAGE_MAP(参数1,参数2),参数1为该类的类名,参数2为该类基类的类名。

4 CalculatorDlg.h

CCalculatorDlg继承自CDialogEx,是窗口类

DECLARE_MESSAGE_MAP:也需要有消息映射。

OnInitDialog: 初始化窗体。

DoDataExchange:把变量和控件绑定

afx_msg void OnButtonBack();  定义消息处理函数

5 Calculator.rc

窗体上各种控件的定义,布局,拖拽控件后自动生成,资源视图中可以修改属性,当然也可以手动修改。

6 Calulator.cpp

主要是InitInstance函数,生成窗体,以模态对话框的形式显示。

CCalculatorDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();

// Calculator.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "Calculator.h"
#include "CalculatorDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CCalculatorApp

BEGIN_MESSAGE_MAP(CCalculatorApp, CWinApp)
    ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CCalculatorApp 构造

CCalculatorApp::CCalculatorApp()
{
    // 支持重新启动管理器
    m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;

    // TODO:  在此处添加构造代码,
    // 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CCalculatorApp 对象

CCalculatorApp theApp;


// CCalculatorApp 初始化

BOOL CCalculatorApp::InitInstance()
{
    // 如果一个运行在 Windows XP 上的应用程序清单指定要
    // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
    //则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    // 将它设置为包括所有要在应用程序中使用的
    // 公共控件类。
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);

    CWinApp::InitInstance();


    AfxEnableControlContainer();

    // 创建 shell 管理器,以防对话框包含
    // 任何 shell 树视图控件或 shell 列表视图控件。
    CShellManager *pShellManager = new CShellManager;

    // 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

    // 标准初始化
    // 如果未使用这些功能并希望减小
    // 最终可执行文件的大小,则应移除下列
    // 不需要的特定初始化例程
    // 更改用于存储设置的注册表项
    // TODO:  应适当修改该字符串,
    // 例如修改为公司或组织名
    SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

    CCalculatorDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO:  在此放置处理何时用
        //  “确定”来关闭对话框的代码
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO:  在此放置处理何时用
        //  “取消”来关闭对话框的代码
    }
    else if (nResponse == -1)
    {
        TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
        TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
    }

    // 删除上面创建的 shell 管理器。
    if (pShellManager != NULL)
    {
        delete pShellManager;
    }

    // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
    //  而不是启动应用程序的消息泵。
    return FALSE;
}

7 CalculatorDlg.cpp

如下定义控件和对象消息响应函数的映射。

BEGIN_MESSAGE_MAP(CCalculatorDlg, CDialogEx)

...

ON_BN_CLICKED(IDC_BUTTON_CHENG, &CCalculatorDlg::OnButtonCheng)

...

END_MESSAGE_MAP()

DDX_Text(pDX, IDC_EDIT1, mStr);   // 把 IDC_EDIT1和mStr绑定。

UpdateData(true); 

UpdateData(TRUE)

——刷新控件的值到对应的变量。(外部输入值交给内部变量)

即:控件的值—>变量。

UpdateData(FALSE)

—— 拷贝变量值到控件显示。(变量的最终运算结果值交给外部输出显示)

即:变量值—>控件显示。

// CalculatorDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "Calculator.h"
#include "CalculatorDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();

// 对话框数据
    enum { IDD = IDD_ABOUTBOX };

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CCalculatorDlg 对话框

CCalculatorDlg::CCalculatorDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(CCalculatorDlg::IDD, pParent)
    , mStr(_T(""))
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCalculatorDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT1, mStr);
}

BEGIN_MESSAGE_MAP(CCalculatorDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()

    ON_BN_CLICKED(IDC_BUTTON_BACK, &CCalculatorDlg::OnButtonBack)
    ON_BN_CLICKED(IDC_BUTTON_CLEAR, &CCalculatorDlg::OnButtonClear)
    ON_BN_CLICKED(IDC_BUTTON_ABOUT, &CCalculatorDlg::OnButtonAbout)
    ON_BN_CLICKED(IDC_BUTTON1, &CCalculatorDlg::OnButton1)
    ON_BN_CLICKED(IDC_BUTTON2, &CCalculatorDlg::OnButton2)
    ON_BN_CLICKED(IDC_BUTTON3, &CCalculatorDlg::OnButton3)
    ON_BN_CLICKED(IDC_BUTTON4, &CCalculatorDlg::OnButton4)
    ON_BN_CLICKED(IDC_BUTTON5, &CCalculatorDlg::OnButton5)
    ON_BN_CLICKED(IDC_BUTTON6, &CCalculatorDlg::OnButton6)
    ON_BN_CLICKED(IDC_BUTTON7, &CCalculatorDlg::OnButton7)
    ON_BN_CLICKED(IDC_BUTTON8, &CCalculatorDlg::OnButton8)
    ON_BN_CLICKED(IDC_BUTTON9, &CCalculatorDlg::OnButton9)
    ON_BN_CLICKED(IDC_BUTTON0, &CCalculatorDlg::OnButton0)
    ON_BN_CLICKED(IDC_BUTTON_DIAN, &CCalculatorDlg::OnButtonDian)
    ON_BN_CLICKED(IDC_BUTTON_CHU, &CCalculatorDlg::OnButtonChu)
    ON_BN_CLICKED(IDC_BUTTON_CHENG, &CCalculatorDlg::OnButtonCheng)
    ON_BN_CLICKED(IDC_BUTTON_JIAN, &CCalculatorDlg::OnButtonJian)
    ON_BN_CLICKED(IDC_BUTTON_JIA, &CCalculatorDlg::OnButtonJia)
    ON_BN_CLICKED(IDC_BUTTON_PINGFANG, &CCalculatorDlg::OnButtonPingfang)
    ON_BN_CLICKED(IDC_BUTTON_KAIFANG, &CCalculatorDlg::OnButtonKaifang)
    ON_BN_CLICKED(IDC_BUTTON_DENG, &CCalculatorDlg::OnButtonDeng)
END_MESSAGE_MAP()


// CCalculatorDlg 消息处理程序

BOOL CCalculatorDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    SetIcon(m_hIcon, TRUE);            // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标

    return TRUE;
}

void CCalculatorDlg::OnButtonBack()
{
    UpdateData(TRUE);
    //移除最右边一个字符  
    if (!mStr.IsEmpty())
    {
        mStr = mStr.Left(mStr.GetLength() - 1);
    }
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButtonClear()
{
    UpdateData(TRUE);
    mStr = L"";
    mNum1 = 0.0f;
    mNum2 = 0.0f;
    mFlag = FLAG_JIA;
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButtonAbout()
{
    CAboutDlg dlg;
    dlg.DoModal();
}

void CCalculatorDlg::OnButton1()
{
    UpdateData(TRUE);
    mStr += L"1";
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButton2()
{
    UpdateData(TRUE);
    mStr += L"2";
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButton3()
{  
    UpdateData(TRUE);
    mStr += L"3";
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButton4()
{
    UpdateData(TRUE);
    mStr += L"4";
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButton5()
{
    UpdateData(TRUE);
    mStr += L"5";
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButton6()
{
    UpdateData(TRUE);
    mStr += L"6";
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButton7()
{
    UpdateData(TRUE);
    mStr += L"7";
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButton8()
{
    UpdateData(TRUE);
    mStr += L"8";
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButton9()
{
    UpdateData(TRUE);
    mStr += L"9";
    UpdateData(FALSE);
}

void CCalculatorDlg::OnButton0()
{
    UpdateData(TRUE);
    mStr += L"0";
    UpdateData(FALSE);
}

//小数点按钮  
void CCalculatorDlg::OnButtonDian()
{
    UpdateData(TRUE);
    //如果没有小数点,则加上一个小数点,如果已有小数点就忽略此次的小数点,保证最多只有1个  
    if (-1 == mStr.Find(L'.'))
    {
        mStr += L".";
    }
    UpdateData(FALSE);
}

//加
void CCalculatorDlg::OnButtonJia()
{
    SaveFirstValue();
    mFlag = FLAG_JIA;

}

//减
void CCalculatorDlg::OnButtonJian()
{
    SaveFirstValue();
    mFlag = FLAG_JIAN;
}

//乘
void CCalculatorDlg::OnButtonCheng()
{
    SaveFirstValue();
    mFlag = FLAG_CHENG;
}

//除
void CCalculatorDlg::OnButtonChu()
{ 
    SaveFirstValue();
    mFlag = FLAG_CHU;
}

//平方
void CCalculatorDlg::OnButtonPingfang()
{
    UpdateData(TRUE);
    mNum1 = _wtof(mStr);
    double f = mNum1 * mNum1;
    //如果浮点数其实是个整数,就显示为整数
    if (f - int(f) <= 1e-5)
    {
        mStr.Format(L"%d", (int)f);
    }
    else
    {
        mStr.Format(L"%f", f);
    }
    UpdateData(FALSE);

    mNum1 = f;
    mNum2 = 0.0f;
    mFlag = FLAG_PINGFANG;
}

//开方
void CCalculatorDlg::OnButtonKaifang()
{
    UpdateData(TRUE);
    mNum1 = _wtof(mStr);
    double f = sqrt(mNum1);
    //如果浮点数其实是个整数,就显示为整数
    if (f - int(f) <= 1e-5)
    {
        mStr.Format(L"%d", (int)f);
    }
    else
    {
        mStr.Format(L"%f", f);
    }
    UpdateData(FALSE);

    mNum1 = f;
    mNum2 = 0.0f;
    mFlag = FLAG_KAIFANG;
}

//等于
void CCalculatorDlg::OnButtonDeng()
{
    Calculator();
}

//保存第一个输入值
void CCalculatorDlg::SaveFirstValue()
{
    UpdateData(TRUE);
    mNum1 = _wtof(mStr);
    mStr = L"";
    UpdateData(FALSE);
}

//计算结果
void CCalculatorDlg::Calculator()
{
    UpdateData(TRUE);
    mNum2 = _wtof(mStr);
    double result = 0.0f;
    switch (mFlag)
    {
    case FLAG_JIA:                        //加  
        result = mNum1 + mNum2;
        break;
    case FLAG_JIAN:                        //减 
        result = mNum1 - mNum2;
        break;
    case FLAG_CHENG:                    //乘  
        result = mNum1 * mNum2;
        break;
    case FLAG_CHU:                        //除  
        if (mNum2 == 0.0f)
        {
            result = mNum1;
        }
        else
        {
            result = mNum1 / mNum2;
        }
        break;
    case FLAG_PINGFANG:                    //平方 
        result = mNum2 * mNum2;
        break;
    case FLAG_KAIFANG:                    //开方  
        result = sqrt(mNum2);
        break;
    default:
        break;
    }
    //如果浮点数其实是个整数,就显示为整数
    if (result - int(result) <= 1e-5)
    {
        mStr.Format(L"%d", (int)result);
    }
    else
    {
        mStr.Format(L"%f", result);
    }
    UpdateData(FALSE);

    mNum1 = result;
    mNum2 = 0.0f;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮华蒲公英

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值