1 Windows 消息按照产生后所走的路经可以分为队列消息和非队列消息。
队列消息:系统产生的消息后首先进入程序的线程消息队列,并且每次从消息队列中取出消息后分发到相应的Window procedure 来处理,其典型的流程如下:
MSG msg;
while( GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
Window Procedure 的典型程序如下:
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_NOTIFY:
….
break;
case WM_COMMAND:
…..
break ;
//other standard windows messages.
case WM_MOUSEMOVE:
…
break;
case WM_XXXX
break;
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
非队列消息:系统产生的消息后不进入线程的消息队列,直接由 Window procedure 来除了,也就是说,控件可能调用了 SendMessage(Msg) 阻塞函数来等待 Window procedure 处理完成后返回。
2 按照消息本身的类型可以分为三类
在 Windows 中,消息有以下三种类型:
(1) 标准 Windows 消息:指以 WM_ 为前缀的那些消息(除了 WM_COMMAND ),如窗口移动消息WM_MOVE ,窗口大小改变消息 WM_SIZE ,此外,如程序启动或退出,窗口创建和关闭等等。
(2) 控件通知消息:由编辑框,列表框等控件或子窗口发给其父窗口的通知消息,以 WM_COMMAND 或WM_NOTIFY (它们之间的区别主要是看 MSG 结构中 lParam 是否为 NULL )为消息名,在消息中包含有控件通知代码,以区分具体的控件通知消息。
(3) 命令消息:命令消息也以 WM_COMMAND 为消息名,在消息中包含有命令的标识符( ID ),以区分具体的命令。命令消息的来源是以下三种用户接口对象:
菜单:用户选择某菜单项,要产生相应的命令消息。
工具栏:用户按下某工具栏按钮产生相应的命令消息。
加速键:用户在键盘上按下了定义的加速键也将产生相应的命令消息。
下面以表格来分析这几类消息:
形式 |
来源 |
谁能处理? |
||
命令消息 |
WM_Command |
菜单、工具栏 |
凡派生自 CcmdTarget 的类,都可以 。范围比较广,比如框架、视图、文档、文档模板、应用程序类等 |
|
通知消息 |
经历了三种演变: 1 、 窗口消息 2 、 命令消息 3 、 WM_Notify |
子控件传给父控件的。只有标准控件能够触发:按钮、列表框、组合框、编辑框、树型控件、列表控件 |
||
一般消息(又叫标准消息、窗口消息) |
有说,除了WM_Command ,其它都属于标准消息, WM_( 任意 ),比如 WM_Create、 WM_Move 等等 |
操作系统、或控制其它窗口的窗口使用 |
凡 派生自 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
{
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 的指针来传递结构地址,根据指针的特性,无论消息有没有附加信息,这个指针都适用,也能够很方便的进行强制转换。我们可以定义自己消息来携带更多的内容,只要这个消息是继承与 NMHDR 即可。