zoukankan      html  css  js  c++  java
  • 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文件中引用。     

    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ 生成的包含文件。
    // 供 Calculator.rc 使用
    //
    #define IDM_ABOUTBOX                    0x0010
    #define IDD_ABOUTBOX                    100
    #define IDS_ABOUTBOX                    101
    #define IDD_CALCULATOR_DIALOG           102
    #define IDR_MAINFRAME                   128
    #define IDC_EDIT1                       1000
    #define IDC_BUTTON_BACK                 1001
    #define IDC_BUTTON_CLEAR                1002
    #define IDC_BUTTON_ABOUT                1003
    #define IDC_BUTTON1                     1004
    #define IDC_BUTTON_PINGFANG             1005
    #define IDC_BUTTON2                     1006
    #define IDC_BUTTON3                     1007
    #define IDC_BUTTON_CHU                  1008
    #define IDC_BUTTON_CHENG                1009
    #define IDC_BUTTON_JIAN                 1010
    #define IDC_BUTTON_JIA                  1011
    #define IDC_BUTTON4                     1012
    #define IDC_BUTTON5                     1013
    #define IDC_BUTTON6                     1014
    #define IDC_BUTTON7                     1015
    #define IDC_BUTTON8                     1016
    #define IDC_BUTTON9                     1017
    #define IDC_BUTTON0                     1018
    #define IDC_BUTTON_DIAN                 1020
    #define IDC_BUTTON_KAIFANG              1021
    #define IDC_BUTTON_DENG                 1022
    
    // Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        129
    #define _APS_NEXT_COMMAND_VALUE         32771
    #define _APS_NEXT_CONTROL_VALUE         1002
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif
    View Code

    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为该类基类的类名。

    // Calculator.h : PROJECT_NAME 应用程序的主头文件
    //
    
    #pragma once
    
    #ifndef __AFXWIN_H__
        #error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
    #endif
    
    #include "resource.h"        // 主符号
    
    
    // CCalculatorApp: 
    // 有关此类的实现,请参阅 Calculator.cpp
    //
    
    class CCalculatorApp : public CWinApp
    {
    public:
        CCalculatorApp();
    
    // 重写
    public:
        virtual BOOL InitInstance();
    
    // 实现
    
        DECLARE_MESSAGE_MAP()
    };
    
    extern CCalculatorApp theApp;
    View Code

    4 CalculatorDlg.h

    CCalculatorDlg继承自CDialogEx,是窗口类

    DECLARE_MESSAGE_MAP:也需要有消息映射。

    OnInitDialog: 初始化窗体。

    DoDataExchange:把变量和控件绑定

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

    // CalculatorDlg.h : 头文件
    
    #pragma once
    
    //运算符
    enum CALCULATOR_FLAG{
        FLAG_JIA = 0,
        FLAG_JIAN,
        FLAG_CHENG,
        FLAG_CHU,
        FLAG_PINGFANG,
        FLAG_KAIFANG,
    };
    class CCalculatorDlg : public CDialogEx
    {
    public:
        CCalculatorDlg(CWnd* pParent = NULL);
    
        enum { IDD = IDD_CALCULATOR_DIALOG };
    
        void SaveFirstValue();        //保存第一个输入值
        void Calculator();            //计算
    public:
        afx_msg void OnButtonBack();
        afx_msg void OnButtonClear();
        afx_msg void OnButtonAbout();
        afx_msg void OnButton1();
        afx_msg void OnButton2();
        afx_msg void OnButton3();
        afx_msg void OnButton4();
        afx_msg void OnButton5();
        afx_msg void OnButton6();
        afx_msg void OnButton7();
        afx_msg void OnButton8();
        afx_msg void OnButton9();
        afx_msg void OnButton0();
        afx_msg void OnButtonDian();
        afx_msg void OnButtonChu();
        afx_msg void OnButtonCheng();
        afx_msg void OnButtonJian();
        afx_msg void OnButtonJia();
        afx_msg void OnButtonPingfang();
        afx_msg void OnButtonKaifang();
        afx_msg void OnButtonDeng();
    protected:
        HICON m_hIcon;
    
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
        virtual BOOL OnInitDialog();
    
        DECLARE_MESSAGE_MAP()
    
    private:
        //编辑框内的字符串
        CString mStr;        
        //输入的2个值  
        double mNum1;
        double mNum2;
        //运算符号
        CALCULATOR_FLAG mFlag;
    };
    View Code

    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, "警告: 对话框创建失败,应用程序将意外终止。
    ");
            TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。
    ");
        }
    
        // 删除上面创建的 shell 管理器。
        if (pShellManager != NULL)
        {
            delete pShellManager;
        }
    
        // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
        //  而不是启动应用程序的消息泵。
        return FALSE;
    }
    View Code

    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;
    }
    View Code
  • 相关阅读:
    Codeforces 632D 暴力
    Codeforces 632C
    nyoj 1070 诡异的电梯 简单dp
    Codeforces 6225B KMP
    Codeforces 631D
    笔记4:多层感知器(自定义模型)
    笔记3:逻辑回归(分批次训练)
    笔记2:张量简介
    笔记1:入门实例
    送快递(贪心+树形结构)
  • 原文地址:https://www.cnblogs.com/liufei1983/p/7140634.html
Copyright © 2011-2022 走看看