mfc
的程式執行的整個流程:
第一步:宣告乙個全域物件
(ex:myobject
在我們自己寫的程式裡頭。)
第二步:由於
winmain()
已經寫好了成
mfc函式,所以它編譯的時候會自動鏈結進來。於是,開始執行
afxwinmain()
第三步:它做什麼動作呢?先取得之前宣告物件的指標,然後開始呼叫
myobject
物件中的
、initinstance()
,及run()(
以上三個函式都是繼承自
第四步:改寫
initinstance()
的動作,在裡頭
new乙個
cframewnd()
的物件。
cframewnd()
這個建構式呼叫
create()。
第五步:
cframewnd
:create()
:做什麼事呢?註冊和建立乙個視窗。
第六步:執行
myobject->run()
。訊息迴圈放在此。
.若是要更改視窗圖示及游標形狀:方法為在rc檔找乙個叫afx_idi_td_frame東東。游標形狀則為呼叫全域函式afxregisterwndclasee()註冊自己的視窗類再將其值傳回,做為create的第乙個引數。
.自己的視窗類別:改寫precreatewindow()。先利用api函式,getclassinof()可以獲得該類別的乙個副本,更改其類別結構的lpszclassname,再以afxregistrtclass
第七步:如何將訊息和程式串接在一起? .
mfc的動態生成:
declare_dynamic:用途為宣告乙個static cruntimeclass資料元素和乙個可以抓到該物件位址的函式getruntimeclass()。
implement_dynamic:~~(
相當於)
_implement_runtimeclass用來將剛剛宣告過的cruntimeclass資料元素,填入初始值。
其中runtime_class用來取得資料元素位址。用途和getruntimeclass()一樣
afx_classinit則是用來串接型錄網用的。(因為它用到了static mpfirstclass指標,借由它的移動,只要一產生新類別就可以串接起來了。)
當然,只用上述的巨集只能完成一些資料的建構,要真的能夠動態生成,則要靠下面的兩個巨集:
1.declare_dyncreate
:(1)
包含declare_dynamic巨集
(2)乙個動態生成的函式:
createobject() 2.
implement_dyncreate:
(1) _implement_runtimeclass
(3) createobject()
的內容。
.mfc
的訊息對映:
如何讓訊息到處亂流,可以往前也可以向左向右?
首先如何建立乙個巨大的訊息網?
1.declare_message_map():用來宣告乙個static messagemap(資料結構為:乙個指向baseclass 的messagemap *指標,和乙個指向messageentry的指標)
、static messageentry、及getmessagemap()。
2.begin_message_map:定義getmessagemap()的內容,及填入messagemap的值。
3.on_command(id,pfn):填入messageentry的內容。
4.end_message_map():填入最後元素內容。
詳細說明:
map
map_entry{
uint nmessage; // windows message
uint ncode; // control code or wm_notify code
uint nid; // control id (or 0 for windows messages)
uint nlastid; // used for entries specifying a range of control id's
uint nsig; // signature type (action) or pointer to message #
afx_pmsgpfn; // 此為函式指標,如左:typedef void (ccmdtarget::*afx_pmsg)(void);
完成之後利用# #definedeclare_message_map()\
static msgmap_entry _messageentries; \
static msgmap messagemap; \
virtual msgmap* getmessagemap() const;
得到乙個
1.map
2.map_entry
3.getmessagemap()//傳回the class map的指標
資料填空的動作由
1.#definebegin_message_map(theclass, baseclass)
\\(1)定義getmessagemap()的內容
\\(2)處理map
\\(3)處理msg_entry
2.#defineon_command(id, memberfxn) \\填入msg_entry
3.#defineend_message_map() \\填入msg_entry的最後乙個元素
整個訊息流動網由上到下建立完成,如下圖。
現在缺的就是由左到右,請問如何做?
一般的訊息
wm_***
,都是由下到上。
但是若是控制項的
wm_command
的話就會有由左到右的可能,要做特別處理。
為了要完成這個目的,需要以下的幾個新函式
上述的結果可以解決上、下流的問題,但是橫的怎麼辦呢?
一般的wm_***一定是上、下流。
但是若是命令wm_command的話就有特別處理了。
怎麼說呢?
請看下面:(call stack執行順序是由下往上看)
ccmdtarget::oncmdmsg()
cview::oncmdmsg()
cframewnd::oncmdmsg()
cwnd::oncommand()
cframewnd::oncmdmsg()
cwnd::oncommand()
cframewnd::oncommand()
cwnd::onwndmsg()
cwnd::windowproc()
afxcallwndproc()
afxwndproc()
afxwndprocbase()
cwinthread::run()
afxwinmain()
winmain()
winmaincrtstartup()
以這個程式為例在cframewnd::oncommand()呼叫了cwnd::oncommand(),而cwnd::oncommand()在函式中又呼叫了oncmdmsg()(此函式為virtual函式),於是cframewnd::oncmdmsg()被喚起,oncmdmsg()虛擬函依序一層一層的被喚起,最後來到ccmdtarget::oncmdmsg()做訊息比對的動作。完
RookeyFrame 整個執行流程
準備開始整理一下這個專案的整體框架,很久沒研究這個框架了,心裡還是念著的,今兒乘有時間弄一下。一丁點建議 先自己乙個乙個的搬作者的類庫,這樣就能很好的理解作者的專案結構 每搬乙個類庫都執行一下哦,看需要引用哪些dll和專案,直到編譯成功後,再進行下一步 自己組建和專案一樣的目錄結構,這樣可以理解一下...
MFC應用程式執行流程
extern c int winapi twinmain hinstance hinstance,hinstance hprevinstance,lptstr lpcmdline,int ncmdshow 這一下清楚了,mfc中的winmain函式其實什麼也沒做,只是呼叫了乙個函式afxwinmai...
MFC 程式入口和執行流程
一 mfc程式執行過程剖析 相信大家有點暈點了吧,實際程式設計中沒有必要深刻理解這麼多,這些大都是由mfc內部自動幫我們完成的。實際mfc程式設計過程中,其實懂得mfc程式中各個函式的執行流程即可。有時候過於追究mfc細節會白白浪費我們的精力,應該將主要精力放在使用mfc解決實際問題上。二 vc6中...