天天看點

VC++學習日志 MFC基礎

轉載位址:HTTP://WWW.CNBLOGS.COM/LTT1987/ARCHIVE/2006/07/23/457845.HTML

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函數前使用::為了和類擴充函數差別 

  直接就可以調:)