VC中的消息的分类有3种:窗口消息、命令消息和控件通知消息,我们这里要谈的是最后一种:控件通知消息。

  控件通知消息,是指这样一种消息,一个窗口内的子控件发生了一些事情,需要通知父窗口。通知消息只适用于标准的窗口控件如按钮、列表框、组合框、编辑框,以及Windows公共控件如树状视图、列表视图等。例如,单击或双击一个控件、在控件中选择部分文本、操作控件的滚动条都会产生通知消息。 她类似于命令消息,当用户与控件窗口交互时,那么控件通知消息就会从控件窗口发送到它的主窗口。但是这种消息的存在并不是为了处理用户命令,而是为了让主窗口能够改变控件,例如加载、显示数据。例如按下一个按钮,他向父窗口发送的消息也可以看作是一个控件通知消息;单击鼠标所产生的消息可以由主窗口直接处理,然后交给控件窗口处理。

  控件通知消息主要由窗口类即直接或间接由CWND类派生类处理。

  控件通知格式

  控件通知经历了一个演变过程,因而SendMessage( )的变量Message、wParam和lParam有三种格式。

  第一控件通知格式

  第一控件通知格式只是窗口消息的子集。它的特征格式如下:WM_XXXX。它主要来自下面的3种消息类型:
   
  (1)表示一个控件窗口要么已经被创建或销毁,要么已经被鼠标单击的消息:WM_PARENTNOTIFY;

  (2)发送到父窗口,用来绘制自身窗口的消息,例如: WM_CTLCOLOR、WM_DRAWITEM、WM_MEASUREITEM、WM_DELETEITEM、WM_CHARTOITEM、WM_VKTOITEM、WM_COMMAND和WM_COMPAREITEM

  (3)有滚动调控件发送,通知父窗口滚动窗口的消息:WM_VSCROLL和WM_HSCROLL

  第二控件通知格式

  第二控件通知格式与命令消息共享,它的特征格式如下:WM_COMMAND。

  在WM_COMMAND中,lParam用来区分是命令消息还是控件通知消息:如果lParam为NULL,则这是个命令消息,否则lParam里面放的必然就是控件的句柄,是一个控件通知消息。对于wParam则是低位放的是控件ID,高位放的是相应的消息事件。

  第三控件通知格式

  这个才真正涉及到我们要讲的内容,同时他也是最为灵活的一种格式。它的特征格式如下:WM_NOTIFY。
在WM_NOTIFY中,lParam中放的是一个称为NMHDR结构的指针。在wParam中放的则是控件的ID。

  NMHDR结构的由来

  NMHDR结构是很值得一提的,该结构包括有关制作该通知的控件的任何内容,而不受空间和类型的限制,他的来历也是很有意思的。

  在最初的windows3.x中,根本就不存在什么WM_NOTIFY,控件通知它们父窗口,如鼠标点击,控件背景绘制事件,通过发送一个消息到父窗口。简单的通知仅发送一个WM_COMMAND消息,包含一个通知码和一个在wParam中的控件ID及一个在lPraram中的控件句柄。这样一来,wParam和lParam就都被填充了,没有额外的空间来传递一些其它的消息,例如鼠标按下的位置和时间。

  为了克服这个困难,windows3.x就提出了一个比较低级的解决策略,那就是给一些消息添加一些附加消息,最为明显的就是控件自画用到的DRAWITEMSTRUCT。不知道大家对这个结构熟悉不,不过,如果你是老手,你应该非常清楚这个结构,这个结构包含了9个内容,几乎你需要控制的信息都给你提供了。为什么说它比较低级呢?因为不同的消息附加的内容不同,结果就是一盘散沙,非常混乱。

在win32中,MS又提出了一个更好的解决方案:引进NMHDR结构。这个结构的引进就是消息统一起来,利用它可以传递复杂的信息。这个结构的布局如下:

NMHDR
{
HWnd hWndFrom ; 相当于原WM_COMMAND传递方式的lParam
UINT idFrom ; 相当于原WM_COMMAND传递方式的wParam(low-order)
UINT code ; 相当于原WM_COMMAND传递方式的Notify Code(wParam"s high-order)
};

  对于这个结构的应用于WM_NOTIFY信息结构,结果WM_NOTIFY就变成了:

  A、无附加信息。结构变得很简单,就是一个NMHDR结构。
  
  B、有附加信息。定义一个大的结构,它的第一个元素就是NMHDR结构,它的后面放置附加信息。

WM_NOTIFY结构的好处

  除了上面我们所说的好处外,WN_NOTIFY还有自己的独特的好处:

  由于在大结构中,第一个成员为NMHDR,这样一来,我们就可以利用指向NMHDR的指针来传递结构地址,根据指针的特性,无论消息有没有附加信息,这个指针都适用,也能够很方便的进行强制转换。

  分析ON_NOTIFY

  类向导可以创建ON_NOTIFY消息映射入口并提供一个处理函数的框架,来处理 WM_NOTIFY类型的消息。ON_NOTIFY消息映射宏有如下语法.

   ON_NOTIFY(wNotifyCode,id,memberFxn)

  其中:wNotifyCode:要处理的通知消息通知码。比如上面我们提到的LVN_KEYDOWN;Id:控件标识ID;MemberFxn:处理此消息的成员函数。

  此成员函数有如下的原型声明:

   afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result);

  比如:假设你想成员函数OnKeydownList1处理ClistCtrl(标识ID=IDC_LIST1)的 LVN_KEYDOWN消息,你可以使用类向导添加如下的消息映射:

   ON_NOTIFY( LVN_KEYDOWN, IDC_LIST1, OnKeydownList1 )

  在上面的例子中,类向导提供如下函数:

   void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
    {
     LV_KEYDOWN* pLVKey= (LV_KEYDOWN*)pNMHDR;
     *pResult = 0;
     }

  这时类向导提供了一个适当类型的指针,你既可以通过pNMHDR,也可以通过 pLVKey来访问这个通知结构。

  ON_NOTIFY_RANGE

  有时我们可能需要为一组控件处理相同的WM_NOTIFY消息。这时需要使用ON_NOTIFY_RANGE而不是ON_NOTIFY。不过,很不幸的是,VC6的ClassWizard并不支持这个消息,所以我们必须手工添加。方法和一般的手工添加的消息一样,不过需要注意的是:

  (1)当你使用 ON_NOTIFY_RANGE时,你需要指定控件的ID范围.其消息映射入口及函数原型如下:

    ON_NOTIFY_RANGE( wNotifyCode, id, idLast, memberFxn )

  其中:wNotifyCode:消息通知码.比如:LVN_KEYDOWN。id: 第一控件的标识ID。
  
   idLast:最后一个控件的标识ID。(标识值一定要连续)memberFxn: 消息处理函数。

  (2)成员函数必须有如下原型申明:afx_msg void memberFxn( UINT id, NMHDR * pNotifyStruct, LRESULT * result );

http://blog.csdn.net/xiexievv/article/details/7580159

全面解读WM_NOTIFY的更多相关文章

  1. SDWebImage源码解读之SDWebImageDownloaderOperation

    第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...

  2. SDWebImage源码解读 之 NSData+ImageContentType

    第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...

  3. SDWebImage源码解读 之 UIImage+GIF

    第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...

  4. SDWebImage源码解读 之 SDWebImageCompat

    第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...

  5. SDWebImage源码解读_之SDWebImageDecoder

    第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...

  6. SDWebImage源码解读之SDWebImageCache(上)

    第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...

  7. SDWebImage源码解读之SDWebImageCache(下)

    第六篇 前言 我们在SDWebImageCache(上)中了解了这个缓存类大概的功能是什么?那么接下来就要看看这些功能是如何实现的? 再次强调,不管是图片的缓存还是其他各种不同形式的缓存,在原理上都极 ...

  8. AFNetworking 3.0 源码解读 总结(干货)(下)

    承接上一篇AFNetworking 3.0 源码解读 总结(干货)(上) 21.网络服务类型NSURLRequestNetworkServiceType 示例代码: typedef NS_ENUM(N ...

  9. AFNetworking 3.0 源码解读 总结(干货)(上)

    养成记笔记的习惯,对于一个软件工程师来说,我觉得很重要.记得在知乎上看到过一个问题,说是人类最大的缺点是什么?我个人觉得记忆算是一个缺点.它就像时间一样,会自己消散. 前言 终于写完了 AFNetwo ...

随机推荐

  1. USACO Healthy Holsteins DFS

    使用排列组合,遍历所有可能的情况C(1)+C(2)+C(3)……C(n)= 2^G种组合 数据规模不大,暴力过去最多也就是2^15 = 23768种情况 所以就暴力咯,不过还是Debug了一会 Sou ...

  2. POJ 2451 Uyuw's Concert(半平面交nlgn)

    //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> # ...

  3. 0.关于TCP协议的一些总结

    接触unix网络编程一年多了,偶尔用户态进程表现出一些不能理解的现象,因此将<TCP/IP协议卷1>TCP协议相关的章节通读了一遍,总结了一下相关的知识点. 1.TCP数据报格式 TCP封 ...

  4. 笔记之Cyclone IV 第一卷第二章Cyclone IV器件的逻辑单元和逻辑阵

    逻辑单元 (LE) 在 Cyclone IV 器件结构中是最小的逻辑单位.LE 紧密且有效的提供了高级功能的逻辑使用.每个 LE 有以下特性 ■ 一个四口输入的查找表 (LUT),以实现四种变量的任何 ...

  5. hdu1540之线段树单点更新+区间合并

    Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  6. [转]CentOS 6.5安全加固及性能优化

    原文链接:http://os.51cto.com/art/201312/423095.htm Centos 6.5 优化 一些基础优化和安全设置 这个也挺好 说明:经常玩Linux系统的朋友多多少少也 ...

  7. CentOS安装postgresql 9.4

    第一步:在CentOS6.5下安装Postgresql 1. 安装PostgreSQL源 # yum install http://yum.postgresql.org/9.4/redhat/rhel ...

  8. day8 - isinstance--issubclass-异常处理-自定义异常

    一.isinstance(obj, cls) 检查是否obj是否是类 cls 的对象 __author__ = 'Administrator' class Foo(object): pass obj ...

  9. pyfits 读取bintable

    import pyfits as pf import numpy as np import math import pandas as pd import matplotlib.pyplot as p ...

  10. X窗口系统名词解释

    前端时间Gentoo的桌面环境出了点问题,发现自己对Linux的桌面环境了解的很少,于是恶补了一下知识,以下名词解释基本上都是来自维基百科的条目和<Linux程序设计(第三版)>.一般而言 ...