ON_NOTIFY不反射消息.如果自己处理不了,就传给上级窗口,如果再处理不了,在往上传.实在处理不了,由框架默认处理.
ON_NOTIFY_REFLECT 反射消息.把消息传给上级窗口处理,如果上级都处理不了,再反射回来,自己处理.
这就是MFC强大的消息反射机制.如果上级窗口处理,则子窗口不处理;
为了项目的需要,往往需要编写自定义控件。当然,很多时候都是在现有控件的基础上进行扩展,在C++中可以用继承来解决。
那么,在MFC列表控件CListCtrl中,如何响应项(Item)的点击事件呢?
首先,在自定义控件类的头文件MyListCtrl.h中定义消息:
protected:
// 生成的消息映射函数
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLvnClickListItem(NMHDR *pNMHDR, LRESULT *pResult);
其次,需要在源文件MyListCtrl.cpp中使用 ON_NOTIFY_REFLECT 声明响应消息:
BEGIN_MESSAGE_MAP(PicListCtrl, CListCtrl)
//}}AFX_MSG_MAP
ON_NOTIFY_REFLECT(NM_CLICK, OnLvnClickListItem)
END_MESSAGE_MAP()
有点头晕,先看看MSDN中是怎么定义的吧。
Map entry |
Function prototype |
---|---|
ON_CONTROL_REFLECT( wNotifyCode, memberFxn ) |
afx_msg void memberFxn ( ); |
原来,是处理控件的点击事件(NM_CLICK),OnLvnClickListItem为响应的函数。
这种事件的响应当然包括控件中没有任何数据项的情况。
但我们只需要在控件中有数据项并且点击到项的时候才处理这些事件,那么就需要在MyListCtrl.cpp中判断一下了:
void MyListCtrl::OnLvnClickListItem(NMHDR *pNMHDR, LRESULT *pResult)
{
//强制转换
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
//判断点击的项个数
if(nItem>=0 && nItem<m_List.GetItemCount()) { .............
//判断双击位置是否在有数据的列表项上面
}//TODO: 在这儿就可以放置项点击的处理代码了
}
ok,,大概就是这个思路了。 消息处理函数中的if语句很重要,用于判断双击位置是否在有数据的列表项上面。因为NM_DBLCLK消息是CListCtrl控件(整体)消息,只要是在CListCtrl控件范围之内执行此事件就会产生该消息,而不一定要在有数据的列表项上面。CListCtrl控件主要事件及LVN_ITEMCHANGED消息和鼠标双击列表项事件的处理
LVN_BEGINDRAG 鼠标左键正在被触发以便进行拖放操作(当鼠标左键开始拖拽列表视图控件中的项目时产生)
LVN_BEGINRDRAG 鼠标右键正在被触发以便进行拖放操作(当鼠标右键开始拖拽列表视图控件中的项目时产生)
LVN_BEGINLABELEDIT 开始编辑项的文本
LVN_COLUMNCLICK 单击列(当鼠标单击列表视图控件列标题时产生)
NM_CLICK 当鼠标单击列表视图控件时产生
LVN_COLUMNCLICK 单击列
LVN_DELETEALLITEMS 删除所有项
LVN_DELETEITEM 删除某个项
NM_DBLCLK 当鼠标双击列表视图控件时产生
LVN_ENDLABELEDIT 结束对项文本的编辑
LVN_GETDISPINFO 请求需要显示的信息
LVN_GETINFOTIP 请求显示在工具提示窗口内的附加的文本信息
LVN_HOTTRACK 鼠标滑过某个项
LVN_INSERTITEM 当向列表视图控件插入项目时产生
lVN_ITEMACTIVATE 激活某个项
LVN_ITEMCHANGED 某个项已经发生变化
LVN_ITEMCHANGING 某个项目正在发生变化
NM_KILLFOCUS 当视表列图控件失去焦点时产生
LVN_KEYDOWN 某个键被按下
LVN_MARQUEEBEGIN 开始某个边框选择
NM_OUTOFMEMORY 当内存溢出时产生
LVN_ODCACHEHINT 虚拟列表控件的显示区域的内容发生了变化
LVN_ODSTATECHANGED 虚拟列表的控件的某个项或某个范围内的项已经发生变化
LVN_ODFINDITEM 需要拥有者查找一个特定的回调项
NM_RCLICK 当鼠标右键单击列表视图控件时产生
NM_RDBLCLK 当鼠标右键双击列表视图控件时产生
NM_SETFOCUS 当列表视图控件获得焦点时产生
LVN_SETDISPINFO 父窗口必须更新控件为项所维护的信息
注解:
HDN:Header Notify LVN:ListView control Notify NM:Notify Message TVN:TreeView control Notify
LVN_ITEMCHANGED消息的处理
消息处理函数:
void C***Dlg::OnItemchangedList(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if(pNMListView->uChanged==LVIF_STATE) { if(pNMListView->uNewState & LVIS_SELECTED) { //处理内容 int nItem=pNMListView->iItem; CString value[6]; for(int i=0;i<6;i++) { value[i]=m_List.GetItemText(nItem,i); } } } *pResult = 0; }
消息处理函数中的两个if条件句一定要有,否则可能出现多次进入处理内容的问题。