1. 子類化
改變一個已經存在的視窗執行個體的性質:訊息處理與其他執行個體屬性。
在SDK編程範疇內,子類化就是改變一個視窗執行個體的視窗函數(通過GetWindowLong()和SetWindowLong()),子類化所要做的就是為某視窗執行個體編寫新的視窗函數。其操作是在執行個體層級上進行的。
在MFC中子類化的情況有所不同:所有MFC視窗有相同的視窗函數,由該視窗函數根據視窗控制代碼尋找視窗執行個體,在把訊息映射到該視窗類別(class)得訊息處理函數上。為了利用MFC的訊息映射機制,不宜改變視窗函數(名),MFC也把子類化封裝在函數SubclassWindow()中。但子類化的本質沒有變:在執行個體層級影響視窗的訊息及其處理。例:
Class B :public A
{
……
}
A a;
B b;
HWND ha=a.GetSafeHwnd();
b.SubclassWindow(ha); #當然A 和B 不一定是繼承關係。
注意:在被子類化的視窗銷毀之前,必須執行視窗的反子類化:
b.UnSubclassWindow();
2 超類化
視窗超類化是在視窗類別——WNDCLASS或WNDCLASSEX(非MFC類概念)層級進行的改變視窗類別特徵的。
使用過程:首先獲得一個已存在的視窗類別,然後設定視窗類別,最後註冊該視窗類別。
例:
WNDCLASSEX wc;
wc.cbSize=sizeof(wc); //Windows用來進行版本檢查的,與視窗特徵無關
GetClassInfoEx(hinst,”XXXXXX”,&wc);
// hinst—定義視窗類別XXXXXX的模組的控制代碼,如為系統定義的視窗類別(如:EDIT、BUTTON)則hinst=NULL.。
wc.lpszClassName = “YYYYYYY”;//必須改變視窗類別的名字
wc.hbrBackGround = CreateSolidBrush(RGB(0,0.0));//改變背景刷
wc.lpfnWndProc = NewWndProc;//改變視窗函數
……
RegisterClassEx(&wc);// 註冊新視窗類別
//使用視窗類別
……
::CreateWindow(_T(“YYYYYYYY”,……);
故超類化只能改變自己建立的視窗的特徵,而不能用於由Windows建立的視窗(如對話方塊上的按鈕就不能進行超類化) 。而子類化是執行個體層級上的,只要能獲得視窗的執行個體,就可對其子類化,這是唯一的子類化對於超類化的優勢。另外,凡是子類化可實現的,超類化都可實現,不過超類化用起來較麻煩。
3. 總結
(0) 子類化修改視窗過程函數, 超類化修改視窗類別(新的視窗類別名)
(1) 子類化是在視窗執行個體層級上的,超類化是在視窗類別(WNDCLASS)層級上的。
(2) 超類化可以完成比子類化更複雜的功能,在SDK範疇上,可以認為子類化是超類化的子集。
(3) 子類化只能改變視窗建立後的性質,對於視窗建立期間無能為力(無法截獲ON_CREATE 事件),而超類化可以實現;超類化不能用於Windows建立的視窗,子類化可以。
4. 其他
在 眼見為實(2):介紹Windows的視窗、訊息、子類化和超類化 這裡有一個例子..
可以得出結論
a) 子類化的classname 是不會變化的, 而超類化使用新註冊classname
b) 子類化 & 超類化 描述的是一個動作 和實現方法沒什麼關係..... 主要是子類化是SubclassWindow, SubclassDlgItem, 而超類化是RegisterClassEx(&newwindowclass)
c) 感覺具體沒有必要區分這些, 實現功能就行了, 呵呵