当前位置 : 主页 > 网络编程 > PHP >

宏ON_NOTIFY与WM_NOTIFY消息

来源:互联网 收集:自由互联 发布时间:2023-09-06
Windows 3.x下的通知消息 在windows 3.x下,控件将诸如鼠标点击、内容修改、选择事件、背景绘制等通知消息发送给父窗口处理。简单的通知消息以WM_COMMAND消息发送,并在wParam参数中存放通


Windows 3.x下的通知消息

在windows 3.x下,控件将诸如鼠标点击、内容修改、选择事件、背景绘制等通知消息发送给父窗口处理。简单的通知消息以WM_COMMAND消息发送,并在wParam参数中存放通知码(如BN_CLICKED)和控件ID,在lParam参数中存放控件句柄。因为wParam与lParam都被使用了,也就没得办法去传递额外的数据。简单的通知消息也有传递额外数据的需求,举个例子,点击事件BN_CLICKED发生时,没有办法去传递鼠标当前的位置信息。

在windows 3.x下,解决上述不能传递额外数据的方法就是定义更多特殊目的的消息,如WM_CTLCOLOR、WM_VSCROLL、WM_HSCROLL、WM_DRAWITEM、WM_MEASUREITEM、WM_COMPAREITEM、WM_DELETEITEM、WM_CHARTOITEM、WM_VKEYTOITEM等等。这些消息可以反射回给控件自己处理,之后由另外一篇译文来介绍这项技术。

Win32下的通知消息

为了兼容存在于Windows 3.1中的诸多控件,Win32 API继续使用了Windows 3.x下的很多通知消息。Win32也为Windows 3.x下支持的控件增加了许多更精细、更复杂的控件(增强版),这些控件在发送通知时,往往需要传递额外的数据。Win32 API的设计者们觉得原来那种增加形如WM_*的Windows消息来解决问题的方式不可取,故设计了一种新的方案,只用一个WM_NOTIFY,这个消息可以传递大量数据。

WM_NOTIFY消息在wParam存放控件ID,而在lParam参数中存放了一个指向一块数据结构的指针,这块数据结构可以是NMHDR或任何第一个成员为NMHDR的更大块的数据结构,之后使用的时候,根据逻辑对这个指针进行相应的类型强转即可。

在大多数情况下,这个指针指向的是一块比NMHDR更大的数据结构,故你在使用时,通常需要进行类型强转。只有少部分公共通知消息(如以NM_打头的消息)及信息提示控件中的TTN_SHOW、TTN_POP通知消息才真正地使用NMHDR。

NMHDR结构包含句柄、发送此消息的控件ID以及消息码(如TTN_SHOW),NMHDR结构定义如下:

typedef struct tagNMHDR {
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR;

对于TTN_SHOW消息,上述结构的code将会被设置为TTN_SHOW。

大多数通知消息传递一个指向第一个成员为NMHDR的大块数据结构。举个例子,当一个按键在list view控件中按下时,List View控件会发送一个LVN_KEYDOW通知消息,这个通知消息的lParam存放的指针指向的数据结构为LV_KEYDOWN,LV_KEYDOWN结构如下:

typedef struct tagLV_KEYDOWN {
NMHDR hdr;
WORD wVKey;
UINT flags;
} LV_KEYDOWN;

注:因为LV_KEYDOWN的第一个成员是NMHDR,所以你可以将lParam中的指针强转成NMHDR*,也可强转成LV_KEYDOWN*。

Windows新控件的通用通知

Windows新控件存在一些通用通知,这个通知传送的是一个NMHDR结构,如下:

通知码(code)

发送来源

NM_CLICK

鼠标左健单击

NM_DBLCLK

鼠标左健双击

NM_RCLICK

鼠标右键单击

NM_RDBLCLK

鼠标右键双击

NM_RETURN

控件拥有输入焦点时,回国事件

NM_SETFOCUS

控件获得输入焦点

NM_KILLFOCUS

控件失去输入焦点

NM_OUTOFMEMORY

控件内存溢出

MFC框架宏ON_NOTIFY

CWnd::OnNotify函数处理通知消息,它的默认实现是检测消息映射数组,查找处理函数并调用。通常来说,你不需要去重写OnNotify,需要做的是针对各种控件事件增加相应的处理函数,并使用MFC提供的宏在消息映射表中添加处理项。

通过MFC提供的类向导,你可以创建ON_NOTIFY入口(即自动在消息映射表中添加处理项)。

ON_NOTIFY消息映射宏的法语如下:

ON_NOTIFY(wNotifyCode, id, memberFxn)

参数说明如下:
wNotifyCode:消息通知码,如LVN_KEYDOWN.
id:控制ID
memberFxn:处理函数,函数原型如下:

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

参数说明如下:
pNotifyStruct:指针,指向第一块内存为NMHDR的数据结束
result:返回结果

举例

假设有个ID为IDC_LIST1的CListCtrl,你要使用OnKeydonwList1来处理其LVN_KEYDOWN的通知消息,你可以使用类向导或手动在消息映射表中添加如下项:

ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, OnKeydownList1)

函数实现如下:

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

// TODO: Add your control notification handler
// code here

*pResult = 0;
}

ON_NOTIFY_RANGE

如果你想为一组控件ID相邻的控件处理同一个WM_NOTIFY消息,你可以使用ON_NOTIFY_RANGE宏来代替ON_NOTIFY。例如,你可能有一组按钮需要对一个通知消息做出一致的响应,就可使用此宏。

类向导没有提供ON_NOTIFY_RANGE宏的自动生成,所以需要自己手动添加。

宏ON_NOTIFY_RANGE原型如下:

ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn)

参数说明如下:
wNotifyCode:通知码,如LVN_KEYDOWN
id:第一个控件ID
idLast:最后一个控件ID
memberFxn:处理函数,函数原型如下:

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

ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE

如果你想让不止一个地方处理通知消息,那么你可以使用宏ON_NOTIFY_EX或ON_NOTIFY_EX_RANGE来实现,带有EX后缀的宏与之前版本的宏的唯一区别在于memberFxn的返回值是BOOL,当返回TRUE时,表示这个通知消息已经处理完毕了,不用再路由给其它地方处理了;而返回FALSE时,表示可以继续交给其它处理器来处理此通知消息。

类向导没有提供ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE宏的自动生成功能,所以这两个宏也是需要你自己手动添加。

ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE宏的原型如下:

ON_NOTIFY_EX(nCode, id, memberFxn)
ON_NOTIFY_EX_RANGE(wNotifyCode, id, idLast, memberFxn)

对应的memberFxn函数原型如下:

afx_msg BOOL memberFxn(UINT id, NMHDR* pNotifyStruct, LRESULT* result);



【文章出处:阜宁网页设计公司 http://www.1234xp.com/funing.html 网络转载请说明出处】
上一篇:Promise异步请求变成同步
下一篇:没有了
网友评论