mfc對window作了一層比較淺的封裝,其建立過程基本與sdk差不多。它簡化了視窗的註冊,並將視窗過程與類關聯起來;後者是比較重要的封裝,它使訊息能夠分流給「類的視窗過程」,既而通過訊息對映,才能到達各個處理函式。
使用傳統的sdk來建立乙個視窗有點繁瑣,偽**是這樣的:
if(registerclass(…))
registerclass
根據乙個classname
註冊乙個視窗類,並指定視窗過程;createwindowex
建立該視窗,其中的引數用於設定樣式、位置等。
這段**的繁瑣之處其實在於函式的引數,createwindowex
有12個引數,這常常讓初學者望而生畏。作為良好封裝的視窗框架,乙個重要任務是簡化這些引數,讓它成為可分別設定的屬性。
要看mfc如何建立乙個視窗,cview
應該是最合適的了,cframewnd::createview
建立了乙個檢視視窗:
cwnd
* cframewnd::createview
(ccreatecontext* pcontext, uint nid)
要建立cview
,只需要乙個cwnd::create
就可以了,不過這裡面必然隱藏著一些事情,包括註冊視窗類,指定視窗過程:
bool cwnd::create
呼叫下面的函式
bool cwnd::createex
(dword dwexstyle, lpctstr lpszclassname, ...)
createex
直接呼叫createwindowex
將視窗建立出來,我們注意到上面呼叫create時傳給lpszclassname
的是乙個空值,那麼視窗類在什麼時候註冊的呢,只有乙個地方,那就是precreatewindow
。precreatewindow
是乙個虛函式,cwnd
在這裡預設地為視窗註冊名字為afxwnd42的視窗類,而派生類可以覆蓋這個函式註冊其他的視窗類名,比如cview
:bool cview::precreatewindow
(createstruct & cs)
return true; }
cview
以afxwndframeorview
註冊視窗類,它的具體名字是:afxframeorview42。註冊的行為就在afxdeferregisterclass
裡面,不過到這裡我們可以打住了。
註冊視窗類的時候要指定視窗過程,afxdeferregisterclass
是乙個巨集,會呼叫afxenddeferregisterclass
作具體的呼叫,在函式裡看到這一句**:wndcls.lpfnwndproc
= defwindowproc;視窗過程竟指定給系統的預設視窗過程,真正的視窗過程是在什麼時候指定的呢?
在cwnd::createex
裡面,createwindowex
的前後各有一行**,從字面上可以推斷mfc監視了視窗的建立:
void
afxapi afxhookwindowcreate(cwnd* pwnd)
mfc使用乙個cbt鉤子來監視視窗的建立,當pwnd
的視窗控制代碼建立時,_afxcbtfilterhook
將被呼叫,這個函式的用意已經非常明顯,將新建立的視窗控制代碼附加到pwnd
,並為pwnd
指定視窗過程。這個函式較長,我就不列**了,只是將大概的幾點列舉如下:
1. 通過cwnd::attach
將控制代碼附加給pwnd
,attach還做了另一件事,建立pwnd
與控制代碼的哈唏表,這是為了後面處理訊息時可以找到正確的cwnd
物件。哈唏表在mfc中大量地被使用。
2.子類化視窗過程,將視窗過程指定為afxwndproc
,並儲存舊的視窗過程;通過presubclasswindow
,你還可以指定自己的視窗過程,不過似乎只在afxwndproc
之後才能被呼叫。
由於整個程序的所有視窗建立都會先被_afxcbtfilterhook
鉤住,所以裡面也進行了一些過濾,比如ime視窗。這種情況對於多執行緒是否有效呢,也許_afxthreadstate
可以確保在多執行緒情況視窗建立的順序,我並沒有去深究。
總而言之,視窗過程最後被替換為afxwndproc
:lresult callback afxwndproc
(hwnd hwnd, uint nmsg, wparam wparam, lparam lparam)
通過fromhandlepermanent
從哈唏表找到與控制代碼對應的視窗類,執行點又進入afxcallwndproc
,接下來我們就會看到熟悉的windowproc
lresult afxapi afxcallwndproc
(cwnd* pwnd, hwnd hwnd, uint nmsg,
wparam wparam = 0, lparam lparam = 0)
pthreadstate
似乎與執行緒同步有關,從這一點可以看出mfc在多執行緒方面做得比vcl好得多,找個時間再來探索這個主題。
到此,視窗建立到訊息處理就連慣起來了。儘管不同的視窗類在處理上有些差異,但核心流程大概就是這樣。
從普通函式到物件方法》。
MFC 使用MFC建立視窗
標頭檔案 mfc是乙個封裝了windowsapi且物件導向的c 類庫,同時也是乙個應用程式的框架結構。另外,並非所有mfc提供的函式都是類的成員,mfc也以 全域性函式的形式,為使用者提供了各類字首為afx的函式,可供使用者在必要時隨時隨地進行呼叫。由mfc建立的應用,我們不能夠直接看到其程式的入口...
MFC視窗訊息
mfc應用程式中處理訊息的順序 1.afxwndproc 該函式負責接收訊息,找到訊息所屬的cwnd物件,然後呼叫afxcallwndproc 2.afxcallwndproc 該函式負責儲存訊息 儲存的內容主要是訊息識別符號和訊息引數 用程式以後使用,然後呼叫windowproc 函式 3.win...
MFC視窗訊息
mfc應用程式中處理訊息的順序 1.afxwndproc 該函式負責接收訊息,找到訊息所屬的cwnd物件,然後呼叫afxcallwndproc 2.afxcallwndproc 該函式負責儲存訊息 儲存的內容主要是訊息識別符號和訊息引數 用程式以後使用,然後呼叫windowproc 函式 3.win...