MFC中删除ListBox最后一项时DeleteItem()未调用的问题咨询
问题描述
我用MFC子类化了CListBox(为适配主题改用CBCGPListBox),目的是删除列表项时给父窗口发送选择变更通知。大部分删除操作都正常生效,但删除最后一项(列表框变为空)时,DeleteItem()虚函数并未被调用。想知道是否存在其他消息或虚函数用于处理这种场景?
class CMyListBox : public CBCGPListBox { virtual void DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct) { __super::DeleteItem(lpDeleteItemStruct); GetParent()->PostMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_SELCHANGE), (LPARAM)m_hWnd); }; };
解决方案
这是MFC列表框的固有行为:当删除最后一项时,系统不会调用DeleteItem()。要覆盖所有删除场景,推荐以下两种处理方式:
重写
RemoveString()函数
所有删除列表项的操作最终都会调用RemoveString(),不管是否是最后一项。重写该函数,在父类执行完成后发送通知,就能覆盖所有删除场景:int RemoveString(UINT nIndex) { int nResult = __super::RemoveString(nIndex); GetParent()->PostMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_SELCHANGE), (LPARAM)m_hWnd); return nResult; }注:
DeleteString()内部也会调用RemoveString(),因此该方法无需额外处理DeleteString()。监听
LBN_DELETESTRING通知(父窗口侧处理)
在父窗口中处理列表框的LBN_DELETESTRING通知,收到通知后检查列表框项数,若为0则手动触发选择变更逻辑。这种方式需要父窗口配合,不如子类内部处理彻底。
补充说明:DeleteItem()仅在列表框销毁单个项(列表仍有其他项)或控件销毁时被调用,删除最后一项时系统会直接清理资源,不会走该虚函数流程,因此需要通过通用删除入口处理。
内容的提问来源于stack exchange,提问作者user3161924
相关产品推荐
相关产品推荐

