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, "警告: 對話框創建失敗,應用程序將意外終止。\n");
        TRACE(traceAppMsg, 0, "警告: 如果您在對話框上使用 MFC 控件,則無法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
    }

    // 刪除上面創建的 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM