一、頭檔案說明
STDAFX.H
這個檔案用來作為Precompile header file,其内隻是載入其他的MFC頭檔案。應用程式通常會準備自己的頭STDAFX.H。
AFXWIN.H
每一個Windows MFC程式都必須載入它,因為它以及它所載入的檔案聲明了所有的MFC類。
在WINDEF.H中有CALLBACK的定義
#define CALLBACK _stdcall //是一種函數調用習慣
在AFXWIN.H中有afx_msg的定義
#define afx_msg //故意安排一個空位置,也許以後版本會用到。
所有MFC頭檔案均置于\MSVC\MFC\INCLUDE中。這些檔案在編譯過程中耗費大量時間,是以有必要設定Precompiled header。一個應用程式在常需要不斷地編譯。Windows程式載入的.H檔案非常巨大但内容不變,編譯器浪費在上面的時間非常多。Precompiled header就是将.H檔案第一次編譯後的結果存儲起來,第二次再編譯時就可以直接從磁盤中取出來用。
二、MFC程式的來龍去脈
CWinApp代表程式本體。CFrameWnd代表一個主架構視窗。必須以這兩個類為基礎,派生自己的類,并改寫其中一部分成員函數。
全局對象theAPP,就是application object。每一個應用程式都應該改寫CWinApp::InitInstance()函數。
MFC把有着相當固定行為的WinMain内部操作封裝在CWinApp中,把有着相當固定行為的WinProc内部操作封裝在CFrameWnd中。
傳統SDK程式WinMain完成的工作,現在由CWinApp的三個函數完成。
Virtual BOOL InitApplication();
Virtual BOOL InitInstance();
Virtual int Run();
CWinApp繼承CWinThread了成員變量m_pMainWnd,代表主視窗。CFrameWnd主要用來掌握一個視窗,它是用來取代SDK程式中的視窗函數的地位。
我們并未寫WinMain程式代碼,這是MFC早已準備好并由連結器直接加到應用程式代碼中的。_tWinMain函數的_t是為了支援UniCode而準備的一個宏。

下面是AfxWinMain代碼。
将以上代碼整理一下就得到下面這段代碼。
AfxGetApp 是一個全局函數,它取得CMyWinApp 對象指針。AfxWinInit 是繼CWinApp 構造式之後的第一個動作。AfxWinInit 之後的動作是pApp->InitApplication。
以上代碼這些動作都是MFC 為了内部管理而做的。繼InitApplication 之後, AfxWinMain 調用pApp->InitInstance。
一般而言,CMyWinApp隻改寫CWinApp中的InitInstance,通常它不改寫InitApplication和Run。
注意:應用程式一定要改寫虛拟函數InitInstance,因為它在CWinApp 中隻是個空函數,沒有任何内建(預設)動作。
CMyWinApp::InitInstance 一開始new 了一個CMyFrameWnd 對象,準備用作主框視窗的C++ 對象。CFrameWnd::Create 在産生視窗之前,會先引發視窗類别的注冊動作。
下面是CreateEx代碼。
調用的PreCreateWindow 是虛拟函數, CWnd 和CFrameWnd 之中都有定義。由于this 指針所指對象的緣故,這裡應該調用的是CFrameWnd::PreCreateWindow。
利用AfxDeferRegisterClass宏注冊視窗類。不同類别的PreCreateWindow 成員函數都是在視窗産生之前一刻被調用,準備用來注冊視窗類别。
CMyFrameWnd::CMyFrameWnd 結束後, 視窗已經誕生出來;程式流程又回到CMyWinApp::InitInstance ,于是調用ShowWindow 函數令視窗顯示出來,并調用UpdateWindow 函數令Hello 程式送出WM_PAINT 消息。
視窗類别注冊好了,視窗誕生并顯示出來了, UpdateWindow 被調用,使得消息隊列中出現了一個WM_PAINT 消息,等待被處理。現在,執行pApp->Run。
Message Map 機制是為了提供更友善的程式接口(例如宏或表格),讓程式員很友善就可以建立起消息與處理例程的對應關系。
MFC 提供給應用程式使用的「很友善的接口」是兩組宏。以Hello 的主視窗為例,第一個動作是在HELLO.H 的CMyFrameWnd 加上DECLARE_MESSAGE_MAP:
第二個動作是在HELLO.CPP 的任何位置(當然不能在函數之内)使用宏如下:
MFC 把消息主要分為三大類, Message Map 機制中對于消息與函數間的對映關系也明定以下三種:
1、标準Windows 消息(WM_xxx)的對映規則:
2、指令消息( WM_COMMAND)的一般性對映規則是:ON_COMMAND(<id>,<memberFxn>)
例如:
ON_COMMAND(IDM_ABOUT, OnAbout)
ON_COMMAND(IDM_FILENEW, OnFileNew)
ON_COMMAND(IDM_FILEOPEN, OnFileOpen)
ON_COMMAND(IDM_FILESAVE, OnFileSave)
3、Notification 消息(由控制元件産生,例如BN_xxx)的對映機制的宏分為好幾種(因為控制元件本就分為好幾種),以下各舉一例做代表:
各個消息處理函數均應以afx_msg void 為函數類型。如果某個消息在Message Map 中找不到對映記錄,它會往基礎類别流竄,這個消息流竄動作稱為Message Routing。如果一直竄到最基礎的類别仍找不到對映的處理例程,由預設函數來處理。
【總結】
凡是由你設計而卻由Windows 系統調用的函數,統稱為callback 函數。這些函數都有一定的類型,以配合Windows的調用動作。
callback 函數是給Windows 調用的, Windows 并不經由任何對象調用這個函數,也就沒有傳遞this 指針給callback 函數,于是導至堆棧中有一個随機變量會成為this 指針,而其結果當然是程式的崩潰了。
要把某個函數用作callback 函數,兩個方法可以做到這一點:
(1)不要使用類的成員函數(也就是說,要使用全局函數)做為callback 函數。
(2)使用static 成員函數。也就是在函數前面加上static 修飾詞。