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文件都重復處理這些文件就顯得很傻了。
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
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;
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; };
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);

// 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; }