子類化(SubclassWindow)技術

2021-06-21 20:35:06 字數 2870 閱讀 6375

視窗子類化的作用

簡單講就是用自定義的視窗過程替換原有的視窗過程,用自定義的視窗過程來處理該視窗的訊息響應。

視窗子類化技術最大的特點就是能夠擷取 windows的訊息。一旦使用者自定義的視窗函式擷取了傳向原視窗函式的訊息,就可以對被擷取的訊息進行如下處理:

將其傳給原來的視窗函式。這是對大多數訊息應該採取的措施,因為子類通常只對原來的視窗特性作少量的改動

擷取該訊息,阻止其向原視窗函式傳送。

修改該訊息,修改完畢以後再向原視窗函式傳送。

windows sdk提供了一些設計好的視窗類,如 edit、 listbox、 treeview等。通過擷取這些通用視窗類的訊息,使用者程式可以為它們新增新的特性,改善其外觀,擴充其功能。

子類化的優點主要體現在以下兩個方面:首先,它不需要建立新的視窗類,不需要了解乙個視窗的視窗過程。這在原來的視窗函式是由別人編寫,而且建立過程不可見的情況下非常有用;其次,子類化比較容易實現,因為所有要做的工作僅僅就是寫乙個視窗函式

在 vc中實現視窗子類化

上面介紹的子類化是從 windows本身的視窗函式概念來講的,實際上屬於 sdk( software development kit)程式設計的範疇,在 mfc中情況有所不同。下面將分別描述在這兩種情況下視窗子類化實現的方法。

vc中基於 sdk程式設計的視窗子類化

vc中基於 sdk程式設計的視窗子類化的基本步驟如下:

(1)      正常建立原始視窗,得到視窗的控制代碼。

(2)      呼叫 getwindowlong得到原來的視窗函式 oldwndproc。

(3)      呼叫 setwindowlong設定新的視窗函式 newwndproc。

新的視窗函式的**如下所示:

lresult newwndproc(hwnd hwnd,uint message,wparam wparam,lparam lparam)

if(message==wm_icareit)

//擷取自己感興趣的訊息,作一些處理,達到改變特性的目的

//必要時可以呼叫原來的視窗函式,使被子類化的視窗仍具有原來的很多特性

return callwndowproc(oldwndproc,hwnd,message,wparam,lparam);

值得注意的是,在呼叫舊的視窗函式時,不能直接用 oldwndproc(…),而必須用函式 callwndproc進行呼叫,否則會出現堆疊錯誤。

mfc程式設計中的視窗子類化

mfc視窗實際上已經是被子類化的視窗。所有的 mfc視窗共享同乙個視窗函式,由這個視窗函式根據視窗控制代碼,查詢這個視窗對應的 cwnd派生類例項,再通過訊息對映這個視窗類的訊息處理函式。鑑於以上原因,在 mfc中要子類化乙個視窗就比較容易了,因為你的任務只是編寫乙個新的 mfc視窗類而不需要寫乙個視窗函式。

假如我們現在有乙個對話方塊,裡面有乙個編輯控制項,我們只希望在該控制項中接受非數字字元輸入,我們可以攔截wm_char訊息,在它的處理函式中忽略任何數字的輸入。 mfc程式設計中視窗子類化的具體實現步驟在下一節筆者將用乙個簡單的例項來加以說明。

vc中視窗子類化的應用舉例

mfc為廣大程式設計者提供了很多功能豐富的視窗類,如果能在這些通用視窗類的基礎上進行子類化的話,將會給程式設計者帶來很多便利。下面舉乙個例子來說明 mfc程式設計中的子類化是多麼的簡單易行。該例完成上面提到的在編輯控制項只接受非數字字元輸入的功能。實現這個子類化的基本步驟和相關**如下:

( 2)對 mfc提供的標準的對話方塊中的控制項進行修改,刪除 mfc提供的靜態文字控制項,新增自己的乙個編輯控制項,設定新控制項的 id為 idc_edit。合理布置對話方塊上各控制項的位置,使程式介面布局合理、美觀。

( 3)用 classwizard從 cedit類派生乙個新的視窗類,新視窗的視窗類叫 cnonumedit。擷取 cnonumedit類的wm_char訊息,在 onchar函中完成忽略任何數字的輸入的處理。實現**如下:

void cnonumedit::onchar(uint nchar, uint nrepcnt, uint nflags)

tchar ch=nchar;

if(ch>=_t(''0'')&&ch<=_t(''9''))

afxmessagebox(("請不要輸入數字! "),mb_ok);

//當輸入數字字元時將被忽略,並顯示警告資訊

return;

cedit::onchar(nchar, nrepcnt, nflags);//輸入為非數字字元時呼叫原處理函式

(4)在對話方塊視窗類 csubclassingdlg的定義中新增變數 cnonumedit ed。在 csubclassingdlg::oninitdialog()函式中呼叫 cwnd類的成員函式 subclasswindow進行子類化。

ed.subclasswindow(getdlgitem(idc_edit)->m_hwnd);

( 5)  在對話方塊視窗類 csubclassing的 ondestroy中呼叫 ed.unsubclasswindow()執行視窗類的反子類化。

現在可以編譯執行這個程式了,當使用者輸入數字字元時將會忽略該輸入,並顯示警告資訊。

在 windows程式設計中,適當使用視窗子類化技術,可以很方便地達到改變乙個視窗的特性的目的。當然子類化也存在其侷限性。實際上,子類化的概念是針對乙個已經建立的視窗來談的,所以修改視窗函式是在視窗建立之後進行的,在視窗建立期間的訊息無法捕獲,也就無法處理。另外有些視窗的特性與視窗類本身的屬性有關。比如如果乙個視窗類沒有 cs_dblclks屬性的話,那麼要想通過子類化這些視窗達到處理 wm_lbuttondblclk訊息的目的是無法實現的。對於子類化的以上侷限性,可以通過超類化( superclassing)技術消除。

視窗的子類化與超類化

1.子類化 改變乙個已經存在的視窗例項的性質 訊息處理與其他例項屬性。在sdk程式設計範疇內,子類化就是改變乙個視窗例項的視窗函式 通過getwindowlong 和setwindowlong 子類化所要做的就是為某視窗例項編寫新的視窗函式。其操作是在例項級別上進行的。在mfc中子類化的情況有所不同...

視窗的子類化與超類化

視窗的子類化與超類化 1.子類化 改變乙個已經存在的視窗例項的性質 訊息處理與其他例項屬性。在sdk程式設計範疇內,子類化就是改變乙個視窗例項的視窗函式 通過getwindowlong 和setwindowlong 子類化所要做的就是為某視窗例項編寫新的視窗函式。其操作是在例項級別上進行的。在mfc...

視窗子類化與超類化

範疇上,可以認為子類化是 超類化的子集。下面分別給出原始碼 子類化 儲存視窗預設的訊息響應函式指標 wndproc psubclassoldeditproc 用於替換子類化視窗的訊息響應函式 lresult callback jceditprocsubclass hwnd hwnd,uint mes...