1、頭文件說明程序員
STDAFX.Happ
這個文件用來做爲Precompile header file,其內只是載入其餘的MFC頭文件。應用程序一般會準備本身的頭STDAFX.H。框架
AFXWIN.H函數
每個Windows MFC程序都必須載入它,由於它以及它所載入的文件聲明瞭全部的MFC類。this
在WINDEF.H中有CALLBACK的定義spa
#define CALLBACK _stdcall //是一種函數調用習慣設計
在AFXWIN.H中有afx_msg的定義指針
#define afx_msg //故意安排一個空位置,也許之後版本會用到。對象
全部MFC頭文件均置於\MSVC\MFC\INCLUDE中。這些文件在編譯過程當中耗費大量時間,因此有必要設定Precompiled header。一個應用程序在常須要不斷地編譯。Windows程序載入的.H文件很是巨大但內容不變,編譯器浪費在上面的時間很是多。Precompiled header就是將.H文件第一次編譯後的結果存儲起來,第二次再編譯時就能夠直接從磁盤中取出來用。blog
2、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 機制中對於消息與函數間的對映關係也明定如下三種:
一、標準Windows 消息(WM_xxx)的對映規則:
二、命令消息( 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)
三、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 修飾詞。