如何在WTL中获取子CListViewCtrl获得焦点的通知?
解决WTL中检测CListViewCtrl焦点状态的方法
首先纠正一个误区:LBN_SETFOCUS是**列表框(CListBox)**的通知消息,不适用于列表视图控件(CListViewCtrl)。列表视图的焦点变更通知是通过WM_NOTIFY消息发送的NM_SETFOCUS和NM_KILLFOCUS通知码,无需子类化控件或发送自定义消息,直接在父窗口中处理即可。
实现步骤
- 在父窗口的消息映射中添加
NM_SETFOCUS和NM_KILLFOCUS的处理函数:
BEGIN_MSG_MAP(CYourParentWindow) // 保留原有其他消息映射 NOTIFY_CODE_HANDLER(NM_SETFOCUS, OnListViewSetFocus) NOTIFY_CODE_HANDLER(NM_KILLFOCUS, OnListViewKillFocus) END_MSG_MAP()
- 实现焦点变更的处理逻辑,通过
pnmh->idFrom判断是哪个列表视图控件:
LRESULT OnListViewSetFocus(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) { if (pnmh->idFrom == IDC_LIST_A) // 替换为你的列表A控件ID { // 处理列表A获得焦点的逻辑,比如标记当前激活列表为A } else if (pnmh->idFrom == IDC_LIST_B) // 替换为你的列表B控件ID { // 处理列表B获得焦点的逻辑,比如标记当前激活列表为B } return 0; } LRESULT OnListViewKillFocus(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) { if (pnmh->idFrom == IDC_LIST_A) { // 可选:处理列表A失去焦点的逻辑 } else if (pnmh->idFrom == IDC_LIST_B) { // 可选:处理列表B失去焦点的逻辑 } return 0; }
针对点击已选中项的场景
当你点击列表A中已选中的项时,虽然不会触发LVN_ITEMCHANGED,但列表A会重新获得焦点,此时NM_SETFOCUS通知会被触发,你可以通过这个通知来感知当前激活的列表是A,完美覆盖你提到的场景。
额外小技巧
如果只是在某个时刻需要判断当前哪个列表有焦点,也可以直接调用::GetFocus(),然后对比控件的HWND:
HWND hFocusWnd = ::GetFocus(); if (hFocusWnd == m_listA.m_hWnd) { // 列表A处于激活状态 } else if (hFocusWnd == m_listB.m_hWnd) { // 列表B处于激活状态 }
内容的提问来源于stack exchange,提问作者bpeikes
相关产品推荐
相关产品推荐

