明明白白看MFC之程序框架(二)

二、 MFC應用程序結構

在《明明白白看MFC之程序框架(一)》中我分析了一個經典的SDK應用程序的結構,現在可是要進入主題“MFC應用程序結構”了。MFC應用程序有好多種,爲了能夠更清楚地與前面的文章形成對比,我們在這裏看一個SDI的應用程序,當然例子還是經典的“Hello World”了。在使用嚮導生成應用程序後,會發現有好幾個文件,首先我們不管有哪些文件,按照程序執行得主線抽取主要的源程序分析一下再說(因爲MFC生成的應用程序不是很方便閱讀,所以在這裏我將他們重新編輯了)。

 

CHelloWorldApp theApp;

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPTSTR lpCmdLine, int nCmdShow)

{

 

CWinThread* pThread = AfxGetThread();

CWinApp* pApp = AfxGetApp();

 

// AFX internal initialization

if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))

goto InitFailure;

 

// App global initializations (rare)

if (pApp != NULL && !pApp->InitApplication())

goto InitFailure;

 

// Perform specific initializations

if (!pThread->InitInstance())

{

if (pThread->m_pMainWnd != NULL)

{

TRACE0("Warning: Destroying non-NULL m_pMainWnd/n");

pThread->m_pMainWnd->DestroyWindow();

}

nReturnCode = pThread->ExitInstance();

goto InitFailure;

}

nReturnCode = pThread->Run();

 

InitFailure:

……………………

 

AfxWinTerm();

return nReturnCode;

}

 

BOOL CWinApp::InitApplication()

{

if (CDocManager::pStaticDocManager != NULL)

{

if (m_pDocManager == NULL)

m_pDocManager = CDocManager::pStaticDocManager;

CDocManager::pStaticDocManager = NULL;

}

 

if (m_pDocManager != NULL)

m_pDocManager->AddDocTemplate(NULL);

else

CDocManager::bStaticInit = FALSE;

 

return TRUE;

}

BOOL CHelloWorldApp::InitInstance()

{

AfxEnableControlContainer();

 

………………………………

 

// Change the registry key under which our settings are stored.

// TODO: You should modify this string to be something appropriate

// such as the name of your company or organization.

SetRegistryKey(_T("Local AppWizard-Generated Applications"));

 

LoadStdProfileSettings(); // Load standard INI file options (including MRU)

 

// Register the application's document templates. Document templates

// serve as the connection between documents, frame windows and views.

 

CSingleDocTemplate* pDocTemplate;

pDocTemplate = new CSingleDocTemplate(

IDR_MAINFRAME,

RUNTIME_CLASS(CHelloWorldDoc),

RUNTIME_CLASS(CMainFrame), // main SDI frame window

RUNTIME_CLASS(CHelloWorldView));

AddDocTemplate(pDocTemplate);

 

// Parse command line for standard shell commands, DDE, file open

CCommandLineInfo cmdInfo;

ParseCommandLine(cmdInfo);

 

// Dispatch commands specified on the command line

if (!ProcessShellCommand(cmdInfo))

return FALSE;

 

// The one and only window has been initialized, so show and update it.

m_pMainWnd->ShowWindow(SW_SHOW);

m_pMainWnd->UpdateWindow();

 

return TRUE;

}

BOOL CWinApp::InitInstance()

{

return TRUE;

}

 

MFC應用程序之“Hello World”

 

咋一眼看上去,好像這個程序無從下手分析,甚至連程序的入口點都找不到。其實,上面的程序還是經過整理後纔有如此模樣。好了,一樣的來看看這個程序是怎麼運行的吧(要注意的事上面的程序來自於不同的文件,這裏排版在一起只是爲了更清楚地表示程序的結構,至於MFC的文件組織我會在下面一個話題中具體的分析,這裏可以暫時不考慮)。

首先,在程序的開始處,首先定義了一個全局變量theApp,我們現在只需要知道他代表了整個程序的存在,然後程序開始介入入口點。有沒有搞錯,入口點在哪裏?不及,其實int AFXAPI AfxWinMain()就是這個程序的入口點,奇怪吧!不過沒有關係,就好像我們第一次看到C語言中的main()函數一樣,只要瞭解就可以了。在AfxWinMain()中分別調用了一些類的成員函數,仿照前面的分析方法,也可以畫出一個程序執行路徑圖。入口點----〉AfxGetThread()------〉AfxGetApp()-------àAfxWinInit()-------àpApp->InitApplication()-----àpThread->InitInstance()------àpThread->Run()。可以看到,程序一樣有一個執行的線索可循,但是,相對於SDK來說,如今已經面目全非了,過去的那種清晰的程序結構在這些程序中也有嗎?答案是肯定的,只不過他們的具體實現在MFC中都進行了包裝而已,那麼,還是來看看這個應用程序是如何啓動並且運行的吧。


程序由AfxWinMain()開始運行後,首先調用了AfxGetApp()來獲取應用程序的對象指針pApp,然後通過這個指針調用有關的成員函數來完成初始化和啓動工作,最後就調用了Run()函數,在這裏,Run()函數就是代表了SDK中的消息循環。

事情的發展在預料中進行着,但是似乎還遺漏了一點什麼似的?不錯,在上面我們的確是還有一樣工作沒有完成,這就是我們需要的”Hello World”好像還沒有輸出來!這不是我的疏忽,而是故意的安排,因爲MFC中採用了一種全新(當然是相對於SDK來說的了)的消息處理機制,至少在表面上來說是這樣的。然而,在這裏我不打算一下子就把問題解決掉,畢竟這有點複雜,等我們明白了MFC的文件之間的關係後我會在回答這個問題。

我沒有想到這篇文章會這麼長,剛剛開始的時候我以爲我可以一下子就把這個問題說清楚地,但是事實上我寫作的思路也像我分析程序時一樣,竟然是一個漫長的過程!所以我也有必要提醒一下自己以及讀這篇文章的朋友,應該休息一下了。我現在都開始慶幸我把這個問題分成好幾個小問題來解決了,我會在接下來的話題中繼續討論的事MFC程序所生成的文件以及它們之間的調用關係。(待續 
 

更多分享請關注:軟信網-編程-http://www.iis365.net.cn

發佈了13 篇原創文章 · 獲贊 5 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章