MFC程式的啟動過程與相關函式執行順序

2021-09-01 19:10:27 字數 3613 閱讀 3998

原文出自:

了解mfc程式的啟動過程,對於初學者來講,了學習mfc很有幫助;對於不常用vc的人來說,過一段時間就會忘記。還是來記下來,方便以後查閱。

2、winmain登場

extern "c" int winapi

_twinmain(hinstance hinstance, hinstance hprevinstance, lptstr lpcmdline, int ncmdshow)

_twinmain函式的「_t」是為了支援unicode而準備的乙個巨集。

_twinmain函式返回值是afxwinmain函式的返回值,afxwinmain函式定義於winmain.cpp第21行,稍加整理,去蕪存菁,就可以看到這個「程式進入點」主要做些什麼事:

afxwininit(hinstance, hprevinstance, lpcmdline, ncmdshow);

afxwinterm();

return nreturncode;

}用過sdk寫程式的朋友,現在可能會發出會心的微笑。

3、afxwininit——afx內部初始化操作

相當於呼叫:

相當於呼叫:

6、cframewnd::create產生主視窗(並先註冊視窗類)

其中create是cframewnd的成員函式,它將產生乙個視窗,用過sdk程式設計序的朋友都知道,要建立主視窗時要先註冊乙個視窗類,規定視窗的屬性等,但,這裡使用哪乙個視窗類呢?create函式第乙個引數(其它引數請參考msdn或《深出淺出mfc》詳解)指定視窗類設為null又是什麼意思啊?意思是要以mfc內建的空中類產生乙個標準的外框視窗,但,我們的程式一般都沒有註冊任何視窗類呀!噢,create函式在產生視窗之前會引發視窗類的註冊操作。

讓我們先挖出create函式都做了些什麼操作,create函式定義於winfrm.cpp的第538行(在此我就不把**copy過來了,你自己開啟出來看吧),函式在562行呼叫createex函式,由於createex是cwnd的成員函式,而cframewnd是從cwnd繼而來,故將呼叫cwnd::createex。此函式定義於wincore.cpp第665行,下面是部分**:

bool cwnd::createex(dword dwexstyle, lpctstr lpszclassname, 

lpctstr lpszwindowname, dword dwstyle,

int x, int y, int nwidth, int nheight,

hwnd hwndparent, hmenu nidorhmenu, lpvoid lpparam)

afxhookwindowcreate(this);

hwnd hwnd = ::createwindowex(cs.dwexstyle, cs.lpszclass,

cs.lpszname, cs.style, cs.x, cs.y, cs.cx, cs.cy,

cs.hwndparent, cs.hmenu, cs.hinstance, cs.lpcreateparams);

...}

用過sdk程式設計序的朋友,看到上面**應該有一點感覺了吧,函式中呼叫的precreatewindows是虛函式,在cwnd和cframewnd之中都有定義。由於this指標所指物件的緣故,這裡應該呼叫的是cframewnd::precreatewindow。該函式定義於winfrm.cpp第521行,以下是部分**:

bool cframewnd::precreatewindow(createstruct& cs)

...}

其中afxdeferregisterclass是乙個定義於afximpl.h中的巨集。該巨集如下:

#define afxdeferregisterclass(fclass) afxenddeferregisterclass(fclass)

注:這裡有巨集和《深入淺出mfc》的不一樣,以上**是從visual c++ 6.0摘取。

afxenddeferregisterclass定義於wincore.cpp第3619行,該函式很複雜,主要是註冊五個視窗類(哇!終於看到視窗類了,怎麼用5個呢?我還不清楚),不同類的precreatewindow成員函式都是在視窗產生之前一刻被呼叫,準備用來註冊視窗類。如果我們指定的視窗類是null,那麼就使用系統預設類。從cwnd及其各個派生類的precreatewindow成員函式可以看出,整個framework針對不同功能的視窗使用了哪些視窗類。

7、視窗顯示與更新

函式呼叫cwinthread::run函式,該函式定義於thrdcore.cpp第456行,在這裡我就不copy出來了。函式在第480行呼叫了pumpmessage函式,該函式定義於thrdcore.cpp第810行,整理後的部分**如下:

bool cwinthread::pumpmessage()

// process this message

if (m_msgcur.message != wm_kickidle && !pretranslatemessage(&m_msgcur))

return true;

}該函式主要操作是將訊息由::dispatchmessage送到視窗函式(cwnd::defwindowproc)中,但程式一般沒有提供任何視窗函式,但在afxenddeferregisterclass中,在註冊五種視窗類之前已經指定視窗函式為:

wndcls.lpfnwndproc = defwindowproc;

雖然視窗函式被指定為defwindowproc成員函式(cwnd::defwindowproc),但事實上訊息並不是被唧往該處,而是乙個名為afxwndproc的全域性函式去。

9、把訊息與處理函式連線在一起——message map機制

到此,主視窗已經產生,等待的就是各種訊息了,然後呼叫相應的處理函式,然而訊息和處理函式怎樣連線在一起呢?mfc採用了message map機制(訊息對映機制),提供給應用程式使用的「很方便的介面」的兩組巨集,其原理我還不大清楚,在這裡也無法講解,主要用法是:先在類宣告中結合declare_message_map()給出處理函式,如:

class cmyframewnd : public cframewnd

再在相應的.cpp檔案的任何位置(當然不能在函式之內)使用bebin_message_map()和end_message_map()巨集把相應的訊息加入去,如:

begin_message_map(cmyframewnd, cframewnd)

on_command(idm_about, onabout)

on_wm_paint()

end_message_map()

總結一下

(2) 呼叫winmain函式完成初始化工作: 通過巨集_twinmain

(3) 初始化工作包括: 視窗類註冊、視窗產生、顯示和更新、訊息迴圈等等

① 註冊視窗類:afxenddeferregisterclass()  //相當於sdk裡面的registerclass()函式

② 建立視窗:cmainframe::precreatewindow()  //允許我們修改視窗屬性的地方

cframewnd::create()

③ 訊息迴圈:pumpmessage()

MFC啟動過程(二)

今天我想看看mfc生成的所有的檔案是幹什麼用的,先從基本的對話方塊程式下手。新建乙個名字為mfc的mfc基本對話方塊程式,編譯連線並執行。之後便會生成所有的檔案,包括exe。以下的截圖便是所有的檔案。res檔案中的東西 debug檔案中的東西 在工程建立之後,編譯執行之前這個資料夾是空的,編譯之後會...

程式編譯過程與軟體啟動過程

一 軟體執行流程 1 軟體編譯流程 預編譯完成巨集展開工作。編譯器合成這些目標檔案成乙個庫檔案 lib 同時解析可以找到的符號引用。此時這個庫檔案包含了二進位制的 段和資料段,同樣也會包含乙個符號表,因為有一些符號需要引用其他靜態 動態鏈結庫的匯出符號。鏈結器負責把目標的庫檔案和所有需要引用的靜態 ...

Cocoa程式啟動過程

詳談cocoa程式啟動過程是本文要介紹的內容,首先,我們的程式執行的時候是物件之間的相互作用,而不是類之間的作用。新建乙個helloword的cocoa程式,可以在xib中找到下面幾個物件 file s owner xib檔案的載入者 firsrt responder 訊息鏈中第乙個能響應相應訊息的...