CListCtrl - MFC 中的一个“金发”类






3.50/5 (45投票s)
2002年12月9日
1分钟阅读

225262
一些对话框代码,
引言
我讨厌 CListCtrl
类。 连同 CTreeCtrl
一起,它是整个 MFC 库中最糟糕、最不完善的类之一。 别争论了,我的想法已经确定,你只会是错的。
问题所在
当我使用列表控件时,我总是使用报告模式。 你们中的许多人可能也只在报告模式下使用 CListCtrl
。 最近,我需要解决 CListCtrl
的一些不足之处。 我还没有理由实际派生一个新的类,但实际上应该这样做。 本文讨论了在对话框类本身中处理这些问题的方法。 派生一个新类并添加此行为留作读者练习。
什么!?没有类似 GetCurSel() 的函数?
CListBox
控件和 CComboBox
控件都有一个函数来检索当前选中项目的索引号。 CListCtrl
没有,所以我使用以下方法。
int CMyDialog::GetSelectedItem() { int nItem = -1; POSITION nPos = m_ctrlMyList.GetFirstSelectedItemPosition(); if (nPos) { nItem = m_ctrlMyList.GetNextSelectedItem(nPos); } return nItem; }
项目高亮显示的问题
好的,你有了你的列表控件,你点击一个项目,正如预期的那样,出现了一个高亮条。很好。 现在,如果你点击列表控件中最后一个项目下方的空白区域,会发生什么? 我告诉你发生了什么 - 高亮条消失了。 这都很好,但是如果你调用我上面给出的函数,它会返回什么索引号? 错了,它不是 -1(正如你可能期望的那样),而是最后一次高亮显示(或选中)项目的索引。 你如何解决它? 处理 OnClick
... 和 OnRclick
... 函数
void CMyDlg::OnClickList(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNM = (NM_LISTVIEW*)pNMHDR; int nCount = m_ctrlList.GetItemCount(); LVHITTESTINFO ht; ht.pt = pNM->ptAction; m_ctrlList.SubItemHitTest(&ht); if (ht.iItem < 0 || ht.iItem > nCount) { int nItem = GetSelectedItem(); // re-establish the highlight bar on the last selected item // (taking advantage of the control's bug) m_ctrlList.SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED); } else { // highlight the item selected m_ctrlHostList.SetItemState(ht.iItem, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED); } *pResult = 0; } void CMyDlg::OnRclickList(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNM = (NM_LISTVIEW*)pNMHDR; int nCount = m_ctrlList.GetItemCount(); if (nCount > 0) { LVHITTESTINFO ht; ht.pt = pNM->ptAction; m_ctrlList.SubItemHitTest(&ht); if (ht.iItem < 0 || ht.iItem > nCount) { int nItem = GetSelectedItem(); m_ctrlList.SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED); } else { m_ctrlList.SetItemState(ht.iItem, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED); } } *pResult = 0; }
玩得开心,记住,我只在报告模式下使用过这个。