CWnd類封裝了所有與窗口操作相關的操作
WinMain函數,它是所有程序的入口函數,在MFC中找不到,但是在鏈接的時候編譯器將他鏈接到我們的程序中,那麼在程序中如何找到呢?
首先搜索(z):\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc(當然是你的anzhaung目錄)下面搜索文件中包含WinMain的文件,會找到appmodul.cpp,然後雙擊打開,可以使用VS打開,會找到WinMain函數。斷點調試可以發現程序確實鏈接了:_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, __in LPTSTR lpCmdLine, int nCmdShow){ // call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);}注意上面的_tWinMain是一個宏,展開還是wWinMain
CMainFrame類名稱是不會變得。其他根據工程名加表示特徵後綴。在MFC中所遇的類都以C開頭。
打開CTestApp類,發現它是從CWinApp派生來的,CWinApp表示一個應用程序類。在類試圖中選中CTestApp類,在下面選擇它的構造函數,如下:CTestApp::CTestApp(){ // TODO: 在此處添加構造代碼, // 將所有重要的初始化放置在 InitInstance 中}// 唯一的一個 CMFC2App 對象
CTestApp theApp;
可以設置斷點,調試,發現程序會首先執行這裏,然後在執行WinMain函數的斷點處。因爲設置了一個CTestApp的全局變量:theApp,可以設置斷點調試,程序會首先執行CTestApp theApp;,然後進入構造函數,然後才進入WinMain函數。這點很重要!全局對象和變量都是在入口函數之前分配內存空間。那麼在這裏CTestApp theApp;爲什麼要定義這樣一個全局對象呢?在一個MFC程序中只能有一個從CWinApp派生來的類,也只能有一個該類的對象。它表示了應用程序本身。基於MFC的應用程序中,使用WinApp對象來表示一個唯一的應用程序。正因爲定義了一個全局對象,所以在程序執行之前就要進行初始化CTestApp類的構造函數,要構造子類的構造函數,會激發父類的構造函數,所以導致了CWinApp的構造函數。因此把派生類和基類關聯起來了。同樣,我們依然在剛纔的路徑下搜索“CWinApp”,會找到appcore.cpp,雙擊打開。可以找到CWinApp的構造函數,CWinApp::CWinApp(LPCTSTR lpszAppName){...............}注意:這裏的構造函數包含一個參數,可是我們在子類中的定義並沒有參數,原因我們可以將鼠標放到CWinApp上右鍵,轉到定義,會發現:CWinApp(LPCTSTR lpszAppName = NULL);這樣一個缺省值爲NULL的定義。所以子類可以不用傳遞這個參數。
接下來看下完整的CWinApp構造函數:
CWINAPP::CWINAPP(LPCTSTR LPSZAPPNAME)
{
IF (LPSZAPPNAME != NULL)
M_PSZAPPNAME = _TCSDUP(LPSZAPPNAME);
ELSE
M_PSZAPPNAME = NULL;
// INITIALIZE CWINTHREAD STATE
AFX_MODULE_STATE* PMODULESTATE = _AFX_CMDTARGET_GETSTATE();
ENSURE(PMODULESTATE);
AFX_MODULE_THREAD_STATE* PTHREADSTATE = PMODULESTATE->M_THREAD;
ENSURE(PTHREADSTATE);
ASSERT(AFXGETTHREAD() == NULL);
PTHREADSTATE->M_PCURRENTWINTHREAD = THIS;
ASSERT(AFXGETTHREAD() == THIS);
M_HTHREAD = ::GETCURRENTTHREAD();
M_NTHREADID = ::GETCURRENTTHREADID();
// INITIALIZE CWINAPP STATE
ASSERT(AFXCURRENTWINAPP == NULL); // ONLY ONE CWINAPP OBJECT PLEASE
PMODULESTATE->M_PCURRENTWINAPP = THIS;
ASSERT(AFXGETAPP() == THIS);
// IN NON-RUNNING STATE UNTIL WINMAIN
M_HINSTANCE = NULL;
M_HLANGRESOURCEDLL = NULL;
M_PSZHELPFILEPATH = NULL;
M_PSZPROFILENAME = NULL;
M_PSZREGISTRYKEY = NULL;
M_PSZEXENAME = NULL;
M_PRECENTFILELIST = NULL;
M_PDOCMANAGER = NULL;
M_ATOMAPP = M_ATOMSYSTEMTOPIC = NULL;
M_LPCMDLINE = NULL;
M_PCMDINFO = NULL;
// INITIALIZE WAIT CURSOR STATE
M_NWAITCURSORCOUNT = 0;
M_HCURWAITCURSORRESTORE = NULL;
// INITIALIZE CURRENT PRINTER STATE
M_HDEVMODE = NULL;
M_HDEVNAMES = NULL;
M_NNUMPREVIEWPAGES = 0; // NOT SPECIFIED (DEFAULTS TO 1)
// INITIALIZE DAO STATE
M_LPFNDAOTERM = NULL; // WILL BE SET IF AFXDAOINIT CALLED
// OTHER INITIALIZATION
M_BHELPMODE = FALSE;
M_EHELPTYPE = AFXWINHELP;
M_NSAFETYPOOLSIZE = 512; // DEFAULT SIZE
}
來看這句:pThreadState->m_pCurrentWinThread = this;將this的值附給pThreadState指針的成員變量m_pCurrentWinThread,這裏的this指針到底指向的是哪一個對像呢?是我們的CTestApp對像還是CWinApp的都像呢?它指向的是派生類CTestApp的對象。也就是剛纔的theApp。
在看WinMain函數,實際上它是用了AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);函數來完成WinMain函數。Afx前綴是屬於應用程序框架類的函數,Application FrameWork x(x這裏沒有什麼意義).
依然是搜索這個函數AfxWinMain,找到winmain.cpp,打開看到:
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
__in LPTSTR lpCmdLine, int nCmdShow)
{
...............
};
因爲C++不是完全面向對象的語言,所以要定義一些全局函數,來組織類之間的關係,這些全局函數我們叫做應用程序框架類的一些函數,以Afx打頭,在每一個類中都可以調用,因爲是全局的。
CWinApp* pApp = AfxGetApp();
這裏AfxGetApp();會獲得一個指向CWinApp的指針,實際上這裏獲得的指針,就是剛纔我們在CWinApp構造函數中附給的這個指針,也就是說這裏pApp指針指向的是派生類CTestApp的theApp指針。
步驟:
設計窗口類
註冊窗口類
創建窗口
顯示窗口
更新窗口
消息循環
消息處理函數
首先效用了InitApplication(),主要是MFC內部管理所調用的函數。
if (pApp != NULL && !pApp->InitApplication())
goto InitFailure;
做個劃線的例子:
HDC hdc; //生成一個HDC的對象
hdc=::GetDC(m_hWnd); //這裏注意:this是c++的關鍵字,表示這個類的當前實例,m_hwnd是一個成員變量,好象是定義在CWnd裏面吧,他存放的是類的實例的句柄
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,Null); //將點移動到具體的位置,API
LindTo(hdc,point.x,point.y); //劃線,API
::ReleaseDC(m_hWnd,hdc); //釋放HDC
關於m_hWnd的疑惑:
this是c++的關鍵字,表示這個類的當前實例,m_hwnd是一個成員變量,好象是定義在CWnd裏面吧,他存放的是類的實例的句柄.、本窗口的句柄
m_hWnd 定義於 CWnd 類,其他類都是從它那裏派生來的。
很簡單常識,一些函數前的兩個冒號::是什麼意思,有什麼用?
作用域標識符.
使用外部命名空間的函數或變量.當外部與模塊內部函數或變量重名時,前面加::可以繼續使用外部的函數或變量,當然,它們必須是可見的。
表明該函數爲全局的而不是當前類的(噹噹前類中沒有該函數時,不加 :: 也是一樣的)
一般是系統API函數
這是調用系統的api函數
呵呵~~
不像vb那樣還要聲明
呵呵~~
系統API函數前使用::爲了和類擴展函數區別
直接就可以調:)