Subclassing一個已有的Windows通用控件,可以減少很多工作量。新的控件可以繼承被subclass的控件的很多能力,如繪制和對滑鼠的響應等。在用MFC ActiveX Control Wizard建立一個工程時,可以選擇Subclass a Windows Control,将生成一些必要的代碼。我們也可以手工向一個已有的ActiveX工程中加入這些代碼:
一、重載COleControl::IsSubclassedControl、PreCreateWindow
BOOL CDemoSubclassCtrl::PreCreateWindow(CREATESTRUCT &cs)
{
cs.lpszClass = _T("BUTTON") ; // 辨別從一個BUTTON容器subclass
return COleControl::PreCreateWindow(cs) ;
}
BOOL CDemoSubclassCtrl::IsSubclassedControl()
return TRUE ;
二、修改OnDraw函數,不需要自己繪制了
void CDemoSubclassCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
DoSuperclassPaint(pdc, rcBounds);
三、處理Reflected容器消息
Windows控件一般都是通過向父視窗發消息和從父視窗接受Reflected消息來實作與父視窗通信的。Reflect消息主要目的在于讓控件有機會控制自己的特性,如WM_CTLCOLOR、WM_DRAWITEM等。
但是ActiveX控件與它的包容器之間的通信機制并不一樣。ActiveX控件通過向包容器發事件和讀取包容器的Ambient屬性來實作和包容器互動的。雖然ActiveX控件也是容器,但它不需要向父視窗發任何消息。事件表面上類似于消息,但内部機制完全不一樣。事件的基礎是連接配接點,而MFC中的消息處理靠的是一條從子類到父類的消息鍊。(具體的可參閱侯捷的《深入淺出MFC》)
但是當一個ActiveX控件subclass了一個Windows控件後,它就會自動地向它的父視窗發消息,如BN_CLICKED。要想辦法不讓它發消息給包容器。為此,COleControl為這種類型的ActiveX控件生成了一個額外的父視窗,名為"reflector",大小和位置與控件一樣。當它接受到控件發出的消息後,它會再發一個reflector消息傳回給控件,以告訴控件它剛才發出了一個什麼樣的消息,這樣控件就能做出相應的處理了,比如再發出事件給包容器。
<col>
Message sent by the control
Message reflected to the control
WM_COMMAND
OCM_COMMAND
WM_CTLCOLORBTN
OCM_CTLCOLORBTN
WM_CTLCOLOREDIT
OCM_CTLCOLOREDIT
WM_CTLCOLORDLG
OCM_CTLCOLORDLG
WM_CTLCOLORLISTBOX
OCM_CTLCOLORLISTBOX
WM_CTLCOLORSCROLLBAR
OCM_CTLCOLORSCROLLBAR
WM_CTLCOLORSTATIC
OCM_CTLCOLORSTATIC
WM_CTLCOLOR
OCM_CTLCOLOR
WM_DRAWITEM
OCM_DRAWITEM
WM_MEASUREITEM
OCM_MEASUREITEM
WM_DELETEITEM
OCM_DELETEITEM
WM_VKEYTOITEM
OCM_VKEYTOITEM
WM_CHARTOITEM
OCM_CHARTOITEM
WM_COMPAREITEM
OCM_COMPAREITEM
WM_HSCROLL
OCM_HSCROLL
WM_VSCROLL
OCM_VSCROLL
WM_PARENTNOTIFY
OCM_PARENTNOTIFY
WM_NOTIFY
OCM_NOTIFY
需要手工加入對reflected message的處理: