ON_NOTIFY http://download.csdn.net/tag/svg
来源:互联网 发布:阿里云备案教程 编辑:程序博客网 时间:2024/06/05 10:50
当自定义控件中发生了特殊的事件需要通知父窗口时,可以向父窗口发送消息,最简单的方法就是直接向父窗口直接发送自定义消息: 然后要做的是定义消息接受函数: (以上第二项是针对控件组的消息映射,这对于那些需要动态生成控件组的应用来说非常有用。) 从消息映射可以看出,每个用户自定义的消息,都被限定在指定的控件上了,并且在NMHDR结构中还有消息源的窗口句柄和消息源的控件ID。因此,用这种方法向父窗口发送通知是不会混淆消息源的,也不需要什么额外的处理。
this->GetParent()->SendMessage(WM_USR1, wParam, lParam);
这种方法简单虽然简单,但是不太干净。因为这样做的前提是要保证WM_USR1消息ID在父窗口的范围内保持唯一,否则父窗口就可能会混淆该消息的来源。而一个窗口中的控件会有很多,并不能保证所有控件的所有消息ID都是唯一的。这就会留下了隐患。
其实有一种更好的,也是标准的解决方案,那就是利用WM_NOTIFY消息向父窗口发送通知。
顾名思义,WM_NOTIFY是专门用于控件向父窗口发送消息的。这个消息与其它的消息不同,用户可以自行定义通知的内容,但传递消息的方式是统一的,程序的处理非常规范、简洁。以下是一点点总结和心得:
【如何发送WM_NOTIFY消息】
发送的方法如下所示:
this->GetParent()->SendMessage(WM_NOTIFY, (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
从上面可以看出无论是发送什么通知,其格式都是统一的:首先利用NMHDR结构体进行包装,然后再作为WM_NOTIFY消息发送出去。而NMHDR结构,既可以使用系统提供的默认结构,也可以根据需要自行进行扩充。
【NMHDR结构体的扩充】
如果仅仅是向父窗口发送一个“通知”,那么使用默认的NMHDR结构体就已经足够了;但若需要同时传递一些附加的信息,就需要对NMHDR结构体进行扩充了。使用WM_NOTIFY发送通知的魅力就在于,用户可以根据自己的需要扩充任何附加信息进去。下面就是自定义的NMHDR结构体:
typedef struct tagMyNMHDR {
注意,这个结构体内包含了NMHDR结构体。这里利用到了C/C++的一个著名的特性:C/C++语言不做内存越界检查。因此,对于自定义的结构体,只要把NMHDR放在第一个元素的地方,就可以安全地把该结构体转型为NMHDR。这样就可以很方便地在WM_NOTIFY消息中发送自定义的附加信息了。
【父窗口如何进行消息影射】
消息发送出去后,父窗口(也就是消息接受方)如何接受这个消息呢?首先是要做消息映射:
ON_NOTIFY(WM_USR1, CTRLID, memberfun1)
afx_msg void memberfun2(UINT id, NMHDR *nmhdr, LRESULT *result);
到此为止,WM_NOTIFY消息从生成、发送,到接受的过程就完成了。再回过头来看看生成NMHDR结构的地方,是否会发现什么问题呢?是的,那就是:
NMHDR结构体的内存应该什么时机进行分配,什么时机进行释放呢?
在上例中,NMHDR结构体是建立在栈上的,在方法执行完毕后,NMHDR所占用的内存将自动被释放,不用担心内存泄露的问题。但是也因此引发一个新问题:如果以异步的形式(PostMessage)发送消息会有什么结果呢?可想而知,在接受方处理消息的时候,发送方很有可能已经结束处理,NMHDR结构也已被自然释放掉了。因此接受方所收到的NMHDR指针已经变成了“野指针”!从而必然引发内存崩溃!危险!
那么,如果把NMHDR建立在堆上,又会如何呢?这样做虽然可以避免了上述野指针的问题,但是已经分配给NMHDR结构体的内存,由谁来释放呢?什么时机释放呢?发送方固然已经无力对其进行释放,由接收方进行释放也是很麻烦的。因为有时会存在消息反射和消息传递的情况,对接收方来说很难判断自己是否是消息处理链的最后一个环节。这使问题复杂化了,同时也违背了“谁分配谁释放”的内存处理原则,稍不留神就会引发内存泄露。
结论:最好不要在堆上建立NMHDR结构体,也不要用PostMessage方法异步发送WM_NOTIFY消息。
- ON_NOTIFY http://download.csdn.net/tag/svg
- http://download.csdn.net/tag/Java
- http://download.csdn.net/download/dev_eric_cf/2818797
- http://download.csdn.net/download/yanxia611/1535119
- http://download.csdn.net/download/soft2buy/6515417
- http://download.csdn.net/download/wanghao200906/8219405
- 配置文件http://tag.csdn.net/tag/SOAP/
- http://download.csdn.net/source/233815
- http://download.csdn.net/source/235908
- http://d.download.csdn.net/source/359168
- http://download.csdn.net/user/csdream
- http://download.csdn.net/down/2049201/heike211
- http://download.csdn.net/down/2049640/xazql
- http://download.csdn.net/source/2534289
- http://download.csdn.net/source/2964033
- http://download.csdn.net/source/1481232
- http://download.csdn.net/user/linhanshi
- http://download.csdn.net/detail/kai27ks/8105497
- 技术工程师-年会(四)
- WP_WP7开发环境搭建(图文教程)
- LED数码管
- ffmpeg 新老接口问题及对照集锦
- Warning: property 'OtherEntrys' not define mapping field , sure?
- ON_NOTIFY http://download.csdn.net/tag/svg
- 技术工程师-年会(五)
- JAVA基础 :request与response转向的区别
- sionFactory与Session区别以及spring事物配置属性的解释
- 性能测试、压力测试、负载测试
- stl模板编程模板参数推导
- (转) NSNotificationCenter
- 关于泛网络游戏模式
- SQL 行列转换