Subclassing a Windows Control

來源:互聯網
上載者:User

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訊息返回給控制項,以告訴控制項它剛才發出了一個什麼樣的訊息,這樣控制項就能做出相應的處理了,比如再發出事件給包容器。

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的處理:

(1)class CDemoSubclassCtrl : public COleControl{protected:LRESULT OnOcmCommand(WPARAM ,LPARAM) ;....} ;(2)BEGIN_MESSAGE_MAP(CDemoSubclassCtrl, COleControL)ON_MESSAGE(OCM_COMMAND, OnOcmCommand)END_MESSAGE_MAP()(3)LRESULT CDemoSubclassCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam){#ifdef _WIN32WORD wNotifyCode = HIWORD(wParam);#elseWORD wNotifyCode = HIWORD(lParam);#endifswitch (wNotifyCode){case BN_CLICKED:FireClick() ;// 一般是發事件給包容器。也可以做別的事情break;}return 0;}同樣的方法,也可以處理OCM_CTLCOLORBTN或OCM_DRAWITEM等訊息來改變按鈕的樣貌。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.