1. 程式人生 > >MFC框架程序及消息映射

MFC框架程序及消息映射

ltr 新窗口 功能 tin pan 組織 upd on() 最終

在一個windows程序中,winmain函數作為程序的入口函數,一個窗口程序是:設計窗口(給窗口設置相應的屬性)——>註冊窗口——>創建窗口——>顯示並且更新窗口——>消息循環;

但是當創建一個MFC程序時候,並沒有看到winmain函數之類的東西,並且之前的程序框架與MFC也大有不同。現在,先來看看MFC中的程序框架以及程序運行機制吧。

由於MFC是對其SDK的封裝,所以程序運行邏輯方式應該是一樣的。

在MFC程序中,同樣還是有winmain函數參與,但是這個WinMain函數是在程序編譯連接時,由鏈接器將該函數鏈接到程序的。知道WinMain的存在後,那麽WinMain又是怎麽跟其他類組織在一起的呢?

(1)CxxxApp 中,有一個theApp對象的全局對象,該對象就表示了應用程序本身。對於全局對象theApp,它是在程序進入WinMain函數之前為其分配的空間,同時,定義其的時候會調用它的構造函數。在程序中看到CxxxApp是 CWinApp的子類,當調用CxxxApp的構造函數之前,會調用其父類的構造函數。程序的初始化在CWinApp構造函數完成。

(2)AfxWinMain函數:WinMain函數實際上是通過調用AfxWinMain函數來完成其功能的。AfxWinMain源代碼在MFC源代碼的WINMAIN.CPP文件中。AfxWinMain首先通過調用AfxGetThread函數獲得一個CWinThread類型的指針,接著調用AfxGetApp函數獲得一個CWinApp類型的指針。由於CWinApp繼承自CWinThread,AfxGetThread函數實際上返回的是AfxGetApp函數的結果,因此上面所說的AfxGetThread函數獲得一個CWinThread類型的指針,接著調用AfxGetApp函數獲得一個CWinApp類型的指針所得到的兩個指針實際上是一致的。都指向theApp全局對象。

(3)InitInstance函數:接下來pThread和pApp調用了三個函數(在AfxWinMain所在的文件WINMAIN.CPP中可以看到)。分別是pApp->InitApplication();

pThread->InitInstance(); pThread->Run();三個函數。這三個函數完成了程序所需要的幾個步驟:設計窗口類,註冊窗口類,顯示窗口類,消息循環,以及窗口過程函數。(通過進一步的跟進每個函數可以發現這三個函數最終需要調用跟win32中程序完成這些功能的函數的影子!)

設計和註冊窗口:MFC 已經為我們預定義了一些默認的標準窗口類,而註冊窗口類是由AfxEndDeferRegisterClass函數完成。 (AfxEndDeferRegisterClass函數首先獲得窗口類的信息,如果該窗口類已經註冊,直接返回一個真值,否則,調用 RegisterClass函數註冊該窗口類。其與win32SDK中所使用的函數是一樣的啊!)

創建窗口: 窗口的創建是由CWnd類中的CreateEx函數實現的,在MFC中,CFrameWnd類的Create函數內部調用了上述的CreateEx函數, 而前者又是由CrameWnd中的LoadFrame函數調用!!!在CreateEx函數的實現過程中,調用了PreCreateWindow,而後者 是一個虛函數,故此調用是調用子類的PreCreateWindow函數,之所以這樣是在窗口產生之前讓程序員能夠有機會修改窗口的外觀。參數類型是一個 CREATESTRUCT結構體。

顯示與更新窗口:CxxxApp類中有一個m_pMainWnd的成員變量,是一個CWnd類型的指針,保存了應用程序窗口的指針。通過它調用與SDK中一樣的ShowWindow與UpdateWindow函數完成任務。

消息循環:前面已經提到過pThread->Run();這個函數就是實現了消息循環。在這個函數中的for循環中,執行了我們認識的TransLateMessage與DisPatchMessage兩個函數;

窗口過程: 在AfxEndDeferRegisterClass函數的源程序中,其中有一行眼熟的代碼:wndcls.lpfnwndProc = DefWindowProc;當然MFC程序並不是把所有的消息都交給DefWindowProc窗口過程來處理。MFC中使用的是消息映射機制!

一個MFC消息響應函數在程序中有三處相關的信息:函數原型,函數實現,用來關聯消息和消息響應函數的宏。(分別分布在頭文件及源文件中)

頭文件中在兩個AFX_MSG 註釋宏之間是消息響應函數的原型的聲明。源文件中有兩處:

(1)AFX_MSG_MAP註釋宏之間的消息映射宏,通過這個宏把消息與消息響應函數關聯起來;

(2)源文件中消息響應函數的實現代碼。

MFC 中的消息映射機制的實現方法:在每個能接收和處理消息的類中,定義一個消息和消息的處理函數靜態對照表,即消息映射表。在消息映射表中,消息與對應的消息處理函數指針成對出現。某個類能處理的所有的消息及其對應的消息處理函數的地址都列在這個類所對應的靜態表中。當有消息需要處理時,程序只要搜索該消息靜態表,查看表中是否存在該消息,就可以知道該類是否能夠處理此消息。如果能,則依照靜態表找到對應的消息處理函數。否則,將消息傳給其父類。

MFC框架程序及消息映射