程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> VC++ >> 明明白白看MFC之程序框架(二)

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

編輯:VC++

二.MFC應用程序結構

  在《明明白白看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程序所生成的文件以及它們之間的調用關系.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved