对于窗口上的控件。控件上的行为会交由窗口处理,也就是控件(或者说系统为控件)发送一个消息通知窗口,这个消息就是WM_NOTIFY.其对应的处理函数是虚函数
OnNotify,所以可以在窗口的OnNotify中给出处理。如果想让控件自己处理,可以重载控件的OnChildNotify函数。
即:
窗口实现OnNotify
控件派生类,并重载OnChildNotify。
消息的路由是:点击控件->窗口OnNotify->控件OnChildNotify。其中窗口传给控件的过程就是所谓的消息反射。
如果采用方法1,至此,消息就完成了,不会再反给窗口。
(1)方法1BOOL CDlgbase3Dlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
// TODO: Add your specialized code here and/or call the base class
if (wParam == IDC_LIST1)
{
NMHDR *pNMHDR = (NMHDR*)lParam;
if (pNMHDR->code == NM_CLICK)
{
OutputDebugString("parent NM_CLICK");
}
}
return CDialog::OnNotify(wParam, lParam, pResult);
}
BOOL CMyClistCtrl::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)
{
// TODO: Add your specialized code here and/or call the base class
if (message == WM_NOTIFY)
{
NMHDR *pNMHDR = (NMHDR*)lParam;
if (pNMHDR->code == NM_CLICK)
{
OutputDebugString("child NM_CLICK");
}
//return FALSE;
}
return CListCtrl::OnChildNotify(message, wParam, lParam, pLResult);
}
(2)方法2
如果要自由控制“控件处理完后是否窗口还可以继续处理”,则需要重写OnNotify。
#include <afxpriv.h>
#include "f:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\AFXIMPL.H"
......
{
// TODO: Add your specialized code here and/or call the base class
ASSERT(pResult != NULL);
NMHDR* pNMHDR = (NMHDR*)lParam;
HWND hWndCtrl = pNMHDR->hwndFrom;
if (pNMHDR->code == NM_CLICK)
{
OutputDebugString("parent NM_CLICK 1");
}
if (ReflectLastMsg(hWndCtrl, pResult))
return TRUE;
if (pNMHDR->code == NM_CLICK)
{
OutputDebugString("parent NM_CLICK 2");
}
UINT nID = _AfxGetDlgCtrlID(hWndCtrl);
int nCode = pNMHDR->code;
AFX_NOTIFY notify;
notify.pResult = pResult;
notify.pNMHDR = pNMHDR;
return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY), ¬ify, NULL);
}
BOOL CMyClistCtrl::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)
{
// TODO: Add your specialized code here and/or call the base class
if (message == WM_NOTIFY)
{
NMHDR *pNMHDR = (NMHDR*)lParam;
if (pNMHDR->code == NM_CLICK)
{
OutputDebugString("child NM_CLICK");
return TRUE;
}
}
return CListCtrl::OnChildNotify(message, wParam, lParam, pLResult);
}
注:ReflectLastMsg函数内部实际调用了控件的OnChildNotify。因此,就可以通过OnChildNotify的返回值来决定窗口的处理。
2.ON_**_REFLECT
在1的描述中,可以看作是一种半手工的方式实现了消息反射(窗口通过ReflectLastMsg调用控件的OnChildNotify)。
实际上,MFC已经提供了一种更方便的方式,也就是真正的消息映射,即在classwizard中前面带有"="的消息。通过classwizard就可以添加。
如。ClistCtrl派生类CMyListCtrl的NM_CLICK消息。
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult);
void CMyClistCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
OutputDebugString("child reflect");
*pResult = 0;
}
但是,这种方式有个缺陷,那就是,窗口无法再通过消息宏ON_NOTIFY(NM_CLICK, IDC_LIST1, OnClickList1)得到通知消息。
如果,既想控件处理,也想窗口也处理,那么窗口仍然要重载OnNotify函数,在这里面截取消息。所以这样的话,倒不如直接用方法1了。