编程-clonne收录界面库wtl学习bobox的移植_第1页
编程-clonne收录界面库wtl学习bobox的移植_第2页
编程-clonne收录界面库wtl学习bobox的移植_第3页
免费预览已结束,剩余7页可下载查看

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

WTLforMFCProgrammingMFCComboBoxWTLWTLClassCComboBoxEx:public{ }ClassCMainDlg:publicCDialogImpl<CMainDlg{}

BOBOXEX,m_cmbEx);件,与DDX_CONTROL不同的是,它不要求控件类由CWindowImpl派生,即不需要包含SubclassWindow()函数这样我们才可以使用DDX来设置我们从CComboBox派生的类(MFC)。CComboBoxExT<TBase>&operator=(HWND{m_hWnd=return}WTLm_hWndCComboBoxEx&operator=(HWND{m_hWnd=return}于是编译通过了。(殊不知潜在的错误就这样被深深的埋起来了DDX_CONTROL_HANDLEDDX_CONTROL_HANDLE整个DDX_MAP其实是定义了一个DoDataExchange函数,BEGIN_DDX_MAP宏定义了函数头,而END_DDX_MAP定义了函数尾,中间一项项的DDX定义函数的具体内容,而当你在代码中定义DDX_MAP#defineBEGIN_DDX_MAP(thisClass)BOOLDoDataExchange(BOOLbSaveAndValidate=FALSE,UINTnCtlID=(UINT)-1)\{bSaveAndValidate;\#defineEND_DDX_MAP()\returnTRUE;\}WTL对于DDX_CONTROL_HANDLECWinDataExchange::DDX_Control_Handle//Simplecontrolattaching(forHWNDwrappercontrols)temte<classTControl>voidDDX_Control_Handle(UINTnID,TControl&ctrl,{

if(!bSave&&ctrl.m_hWnd=={T*pT=static_cast<T*>(this);ctrl=pT->GetDlgItem(nID);}}WTL正如上面的代码,DDX_CONTROL_HANDLE宏是直接将ID所对应的窗体句柄直接赋值给DDX所的控件类于是我们在DDX_MAP中定义的语句与下面的语句m_cmbEx=this->GetDlgItem(DDX_CONTROL_HANDLE试了。当然如果你熟悉WTL或者仔细看了上面的代码,也许会发现有一个很大的问题潜伏着。可是我们是MFC的程序员,习惯用MFC的方法去思考,于是奇怪的画没有被触发。为什么?我们的所有代码都是按照正确的方法写成的,在CComboBoxEx的MSG_MAP中添加MSG_OCM_DRAWITEM宏来映射重画,在CMainDlg的MSG_MAPREFLECT_NOTIFICATIONS()宏。于是我们在来的类添加这个结果错误出现了,提示没有DefaultReflectionHandler#defineDEFAULT_REFLECTION_HANDLER()if(DefaultReflectionHandler(hWnd,uMsg,ram,lResult))returnATLDEFAULT_REFLECTION_HANDLERDefaultReflectionHandler数,那么这个函数又是何许人也呢?DefaultReflectionHandler是CWindowImplRoot的成员函数,也可以说是CWindowImpl的成员函数,因为CWindowImplCWindowImplBase派生CWindowImplBaseCWindowImplRoot派生,DefaultReflectionHandler函数其实是对API函数DefWindowProc的封装,不过它只限于处理OCM_的。如下面的代码:temte<classBOOLCWindowImplRoot<TBase>::DefaultReflectionHandler(HWNDhWnd,UINTuMsg,RAMram,LPARAMlParam,LRESULT&lResult){{ caseOCM_NOTIFY:casecasecase casecasecasecasecasecasecasecasecasecasecasecaselResult=::DefWindowProc(hWnd,uMsg-OCMBASE,}

returnTRUE;return}看到这里,如果想添加DEFAULT_REFLECTION_HANDLER宏,控件类就要由CWindowImpl这样:classCComboBoxEx:publicCWindowImpl<CComboBoxEx,于是添加DEFAULT_REFLECTION_HANDLER宏得操作通过了编译但是事实证明,ATL这个错误到让我们想到原书中提到的一个WTL特性WTL不会自动销毁窗体句柄,Detach()窗体句柄。既然这样,我们又添加了下面的代码:boBoxEx(){虽然没有Attach()的Detach()感觉有点怪可是毕竟ATL的断言不会出现了。但是,问题并没有解决,重画还是没有被触发。难道是CMainDlg没有反射回来?看看用来反射的REFLECT_NOTIFICATIONS宏的代码:#defineREFLECT_NOTIFICATIONS(){bHandled=TRUE;lResult=ReflectNotifications(uMsg,ram,lParam,\if(bHandled)returnTRUE;}ATLREFLECT_NOTIFICATIONS temte<class RAMram,LPARAMlParam,BOOL&bHandled){HWNDhWndChild=NULL;{ if(lParam!=NULL)//notfromahWndChild=(HWND)lParam;casehWndChild=((LPNMHDR)lParam)->hwndFrom;caseswitch(LOWORD({casecasehWndChild=hWndChild=GetDlgItem(HIWORD(ram));}caseif( //notfromcase

//notfrom GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)- if( //notfrom caseif( //notfrom GetDlgItem(((LPDELETEITEMSTRUCT)lParam)-casecasecasecasehWndChild=(HWND)lParam;caseWM_CTLCOLORBTN:caseWM_CTLCOLORDLG:caseWM_CTLCOLOREDIT:caseWM_CTLCOLORLISTBOX:caseWM_CTLCOLORMSGBOX:caseWM_CTLCOLORSCROLLBAR:caseWM_CTLCOLORSTATIC:hWndChild=(HWND)lParam;}}}

if(hWndChild=={bHandled=FALSE;return1;return::SendMessage(hWndChild,OCMBASE+uMsg,ATL我们感的是最后一句,控件接收到的是ID=OCMBASE+WM_DRAWITEM的消息,那么我们可以让控件直接接收消息(OCMBASEMSG_OCM_DRAWITEM代码:MESSAGE_HANDLER_EX(OCMBASE+WM_DRAWITEM,但是结果还是一样-重画没有被触发CMainDlg中添加了 结果捕抓到了CComboBoxEx的重 CMainDlg::OnDrawItem()中添加了SendMessage(m_cmbEx.m_hWnd,OCMBASE+WM_DRAWITEM,0,以取代REFLECT_NOTIFICATIONS宏所做的自动反射,结果发现,还是没有收到难道WTL处理出了问题?我们又为CComboBoxEx添加了非反射的事件WM_PAINT,结果发现WM_PAINT也没有被触发!!!CComboBoxEx根本无法收到任何《程序员之道》说当你想说这不可能的时候,往往是你在调用的方法我们重新回到起点,来看看那里出了错。仔细地研读代码以后发现,是怎么传递到MSG_MAP的呢?难道我们通过赋值将一个窗体句柄传进来,我们在这个类中定义的MSG_MAP就能自动的连接到这个句柄上吗?这显然是真的不那么没有将MSG_MAP连接到窗体句柄很可能是控件类无法收到任何的MSG_MAPCComboBoxEx&operator=(HWNDhWnd){CWindowImpl<CComboBoxEx,return}一测之下,大吃一惊。不仅重画被正确触发,连析构函数中的AttachDetachDDX_CONTROLCWindowImpl的派生类起作用-是怎么回事。原码如下:

#defineDDX_CONTROL(nID,obj)if(nCtlID==(UINT)-1||nCtlID==nID)\DDX_Control(nID,obj,bSaveAndValidate);//Fullcontrolsubclassing(forCWindowImpltemte<classvoidDDX_Control(UINTnID,TControl&ctrl,BOOL{if(!bSave&&ctrl.m_hWnd=={T*pT=ctrl.SubclassWindow(pT-;}}从原码可以看到,DDX_CONTROLDDX_CONTROL_HANDLERSubclassWindow,而后者使用操作符“=”。如果把我SubclassWindow,DDX_CONTROL_HANDLERDDX_CONTROL3DDX_CONTROLCComboBoxSubclassWindowCComboBoxMFCCComboBoxExCComboBoxCWindowImpl<CComboBoxEx,CComboBox>这样怪怪的方法。可是这里忽视了一个基本的WTL特性,由于WTL基于ATL,而设计ATL就是为了将接口 分开,所以在WTL中所有不带Impl字样的类都不是实现类,像CWindow,CButton,CComboBox等等,他们只是包含一个句柄,没有自己的,他们只是负责中转,封装控件等等。像CComboBox的操作符“=”就只是一个赋值语句而已。而DDX_CONTROL_HANDLER正是为这些类服务//Fullcontrolsubclassing(forCWindowImplderivedcontrols)temte<classTControl>voidDDX_Control(UINTnID,TControl&ctrl,BOOL//Simplecontrolattaching(forHWND

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论