WTL_消息处理.doc_第1页
WTL_消息处理.doc_第2页
WTL_消息处理.doc_第3页
WTL_消息处理.doc_第4页
WTL_消息处理.doc_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

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

文档简介

处理控件发送的通知消息在WTL中处理通知消息与使用API方式编程相似,控件以WM_COMMAND 或 WM_NOTIFY 消息的方式向父窗口发送通知事件,父窗口相应并做相应处理。少数其它的消息也可以看作是通知消息,例如:WM_DRAWITEM,当一个自画控件需要画自己时就会发送这个消息,父窗口可以自己处理这个消息,也可以再将它反射给控件,MFC采用得就是消息反射方式,使得控件能够自己处理通知消息,提高了代码的封装性和可重用性。在父窗口中响应控件的通知消息以WM_NOTIFY和WM_COMMAND消息形式发送的通知消息包含各种信息。WM_COMMAND消息的参数包含发送通知消息的控件ID,控件的窗口句柄和通知代码,WM_NOTIFY消息的参数还包含一个NMHDR数据结构的指针。ATL和WTL有各种消息映射宏用来处理这些通知消息,我在这里只介绍WTL宏,因为本文就是讲WTL得。使用这些宏需要在消息映射链中使用BEGIN_MSG_MAP_EX并包含atlcrack.h文件。消息映射宏要处理WM_COMMAND通知消息需要使用COMMAND_HANDLER_EX宏:COMMAND_HANDLER_EX(id, code, func) 处理从某个控件发送得某个通知代码。 COMMAND_ID_HANDLER_EX(id, func) 处理从某个控件发送得所有通知代码。 COMMAND_CODE_HANDLER_EX(code, func) 处理某个通知代码得所有消息,不管是从那个控件发出的。 COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) 处理ID在idFirst和idLast之间得控件发送的所有通知代码。 COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) 处理ID在idFirst和idLast之间得控件发送的某个通知代码。 例子: COMMAND_HANDLER_EX(IDC_USERNAME, EN_CHANGE, OnUsernameChange): 处理从ID是IDC_USERNAME的edit box控件发出的EN_CHANGE通知消息。 COMMAND_ID_HANDLER_EX(IDOK, OnOK): 处理ID是IDOK的控件发送的所有通知消息。 COMMAND_RANGE_CODE_HANDLER_EX(IDC_MONDAY, IDC_FRIDAY, BN_CLICKED, OnDayClicked): 处理ID在IDC_MONDAY和IDC_FRIDAY之间控件发送的BN_CLICKED通知消息。 还有一些宏专门处理WM_NOTIFY消息,和上面的宏功能类似,只是它们的名字开头以“NOTIFY_”代替“COMMAND_”。WM_COMMAND 消息处理函数的原型是: void func ( UINT uCode, int nCtrlID, HWND hwndCtrl );WM_COMMAND通知消息不需要返回值,所以处理函数也不需要返回值,WM_NOTIFY消息处理函数的原型是: LRESULT func ( NMHDR* phdr );消息处理函数的返回值用作消息相应的返回值,这不同于MFC,MFC的消息响应通过消息处理函数的LRESULT*参数得到返回值。发送通知消息的控件的窗口句柄和通知代码包含在NMHDR结构中,分别是code和hendFrom成员。和MFC一样的是如果通知消息发送的不是普通的NMHDR结构,你的消息处理函数应该将phdr参数转换成正确的类型。我们将为CMainDlg添加LVN_ITEMCHANGED通知的处理函数,处理从list控件发出的这个通知,在对话框中显示当前选择的项目,先从添加消息映射宏和消息处理函数开始:class CMainDlg : public . BEGIN_MSG_MAP_EX(CMainDlg) NOTIFY_HANDLER_EX(IDC_LIST, LVN_ITEMCHANGED, OnListItemchanged) END_MSG_MAP() LRESULT OnListItemchanged(NMHDR* phdr);/.;下面是消息处理函数:LRESULT CMainDlg:OnListItemchanged ( NMHDR* phdr )NMLISTVIEW* pnmlv = (NMLISTVIEW*) phdr;int nSelItem = m_wndList.GetSelectedIndex();CString sMsg; / If no item is selected, show none. Otherwise, show its index. if ( -1 = nSelItem ) sMsg = _T(none); else sMsg.Format ( _T(%d), nSelItem ); SetDlgItemText ( IDC_SEL_ITEM, sMsg ); return 0; / retval ignored该处理函数并未用到phdr参数,我将他强制转换成NMLISTVIEW*只是为了演示用法。反射通知消息如果你是用CWindowImpl的派生类封装控件,比如前面使用的CEditImpl,你可以在类的内部处理通知消息而不是在对话框中,这就是通知消息的反射,它和MFC的消息反射相似。不同的是在WTL中父窗口和控件都可以处理通知消息,而在MFC中只有控件能处理通知消息(译者加:除非你重载 WindowProc函数,在MFC反射这些消息之前截获它们)。如果需要将通知消息反射给控件封装类,只需在对话框的消息映射链中添加REFLECT_NOTIFICATIONS()宏:class CMainDlg : public .public: BEGIN_MSG_MAP_EX(CMainDlg) /. NOTIFY_HANDLER_EX(IDC_LIST, LVN_ITEMCHANGED, OnListItemchanged) REFLECT_NOTIFICATIONS() END_MSG_MAP();这个宏向消息映射链添加了一些代码处理那些未被前面的宏处理的通知消息,它检查消息传递的HWND窗口句柄是否有效并将消息转发给这个窗口,当然,消息代码的数值被改变成OLE控件所使用的值,OLE控件有与之相似的消息反射系统。新的消息代码值用OCM_xxx代替了WM_xxx,但是消息的处理方式和未反射前一样。有18中被反射的消息: 控件通知消息: WM_COMMAND, WM_NOTIFY, WM_PARENTNOTIFY 自画消息: WM_DRAWITEM, WM_MEASUREITEM, WM_COMPAREITEM, WM_DELETEITEM List box 键盘消息: WM_VKEYTOITEM, WM_CHARTOITEM 其它: WM_HSCROLL, WM_VSCROLL, WM_CTLCOLOR* 在你想添加反射消息处理的控件类内不要忘了使用DEFAULT_REFLECTION_HANDLER()宏,DEFAULT_REFLECTION_HANDLER()宏确保将未被处理的消息交给DefWindowProc()正确处理。 下面的例子是一个自画按钮类,它相应了从父窗口反射的WM_DRAWITEM消息。class CODButtonImpl : public CWindowImplpublic: BEGIN_MSG_MAP_EX(CODButtonImpl) MSG_OCM_DRAWITEM(OnDrawItem) DEFAULT_REFLECTION_HANDLER() END_MSG_MAP() void OnDrawItem ( UINT idCtrl, LPDRAWITEMSTRUCT lpdis ) / do drawing here. ;用来处理反射消息的WTL宏 我们现在只看到了WTL的消息反射宏中的一个:MSG_OCM_DRAWITEM,还有17个这样的反射宏。由于WM_NOTIFY和WM_COMMAND消息带的参数需要展开,WTL提供了特殊的宏MSG_OCM_COMMAND和MSG_OCM_NOTIFY做这些事情。这些宏所作的工作与COMMAND_HANDLER_EX和NOTIFY_HANDLER_EX宏相同,只是前面加了“REFLECTED_”,例如,一个树控件类可能存在这样的消息映射链:class CMyTreeCtrl : public CWindowImplpublic: BEGIN_MSG_MAP_EX(CMyTreeCtrl) REFLECTED_NOTIFY_CODE_HANDLER_EX(TVN_ITEMEXPANDING, OnItemExpanding) DEFAULT_REFLECTION_HANDLER() END_MSG_MAP() LRESULT OnItemExpanding ( NMHDR* phdr );在ControlMania1对话框中用了一个树控件,和上面的代码一样处理TVN_ITEMEXPANDING消息,CMainDlg类的成员m_wndTree使用DDX连接到控件上,CMainDlg反射通知消息,树控件的处理函数OnItemExpanding()是这样的:LRESULT CBuffyTreeCtrl:OnItemExpanding ( NMHDR* phdr )NMTREEVIEW* pnmtv = (NMTREEVIEW*) phdr; if ( pnmtv-action & TVE_COLLAPSE ) return TRUE; / dont allow it else return FALSE; / allow it运行ControlMania1,用鼠标点击树控件上的+/-按钮,你就会看到消息处理函数的作用节点展开后就不能再折叠起来。容易出错和混淆的地方对话框的字体如果你像我一样对界面非常讲究并且正在只用windows 2000或XP,你就会奇怪为什么对话框使用MS Sans Serif字体而不是Tahoma字体,因为VC6太老了,它生成的资源文件在NT 4上工作的很好,但是对于新的版本就会有问题。你可以自己修改,需要手工编辑资源文件,据我所知VC 7不存在这个问题。在资源文件中对话框的入口处需要修改3个地方:1. 对话框类型: 将DIALOG改为DIALOGEX 2. 窗口类型: 添加DS_SHELLFONT 3. 对话框字体: 将MS Sans Serif改为MS Shell Dlg 不幸的是前两个修改会在每次保存资源文件时丢失(被VC又改回原样),所以需要重复这些修改,下面是改动之前的代码:IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 187, 102STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENUCAPTION AboutFONT 8, MS Sans SerifBEGIN .E

温馨提示

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

最新文档

评论

0/150

提交评论