CListCtrl - Selection Problem
-
VC6, SP5 I have a CListCtrl in a CDialog. In ClassWizard, I turned on "Show Selection Always", and in OnInitDialog, I've turned on the LVS_EX_FULLROWSELECT | LVS_EX_ONECLICKACTIVATE extended styles for the list control. After clicking on an item, it highlights (as expected). When I click on an area of the listcontrol that does not have an item, the highlight goes away for the last selected item, but the program still thinks it's selected. If I click a number of times in the empty area, the highlight comes and goes. If I click on the item again, the highlight comes back. I want to do one of two things: 1) Do not allow the highlight to be removed from the selected item when I click on the empty control area (this is the preferred method). 2) Un-select the item when I click on the empty control area. I'm trying to avoid subclassing the CListCtrl because there's a lot more issues involved with doing so. Opinion - MFC's CListCtrl class SUCKS. ------- signature starts "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001 Please review the Legal Disclaimer in my bio. ------- signature ends
-
VC6, SP5 I have a CListCtrl in a CDialog. In ClassWizard, I turned on "Show Selection Always", and in OnInitDialog, I've turned on the LVS_EX_FULLROWSELECT | LVS_EX_ONECLICKACTIVATE extended styles for the list control. After clicking on an item, it highlights (as expected). When I click on an area of the listcontrol that does not have an item, the highlight goes away for the last selected item, but the program still thinks it's selected. If I click a number of times in the empty area, the highlight comes and goes. If I click on the item again, the highlight comes back. I want to do one of two things: 1) Do not allow the highlight to be removed from the selected item when I click on the empty control area (this is the preferred method). 2) Un-select the item when I click on the empty control area. I'm trying to avoid subclassing the CListCtrl because there's a lot more issues involved with doing so. Opinion - MFC's CListCtrl class SUCKS. ------- signature starts "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001 Please review the Legal Disclaimer in my bio. ------- signature ends
These aren't problems with
CListCtrl
per se, but the Windows list-view control underneath, which is an A-number-1 mother-batch when it comes to handling selections. The essence of modifying the selection behavior is to handle theLVN_ITEMCHANGING
andLVN_ITEMCHANGED
notifications.LVN_ITEMCHANGING
lets you decide whether or not to permit a state change in a list view item. In this case, you could find out where the user clicked and use that to make the decision.LVN_ITEMCHANGED
tells you after an item's state changed.
Software Zen:
delete this;
-
These aren't problems with
CListCtrl
per se, but the Windows list-view control underneath, which is an A-number-1 mother-batch when it comes to handling selections. The essence of modifying the selection behavior is to handle theLVN_ITEMCHANGING
andLVN_ITEMCHANGED
notifications.LVN_ITEMCHANGING
lets you decide whether or not to permit a state change in a list view item. In this case, you could find out where the user clicked and use that to make the decision.LVN_ITEMCHANGED
tells you after an item's state changed.
Software Zen:
delete this;
I ended up doing this (pardon the formatting - I cut/pasted the code from my source, and CP's "code" tags seem to be ignoring the tabs that are there):
void CConfigDlg::OnClickHostlist(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNM = (NM_LISTVIEW*)pNMHDR; int nCount = m_ctrlHostList.GetItemCount(); LVHITTESTINFO ht; ht.pt = pNM->ptAction; m_ctrlHostList.SubItemHitTest(&ht); if (ht.iItem < 0 || ht.iItem > nCount) { int nItem = GetSelectedItem(); m_ctrlHostList.SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED); } else { m_ctrlHostList.SetItemState(ht.iItem, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED); } // ... other code ... *pResult = 0; } void CConfigDlg::OnDblclkHostlist(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNM = (NM_LISTVIEW*)pNMHDR; int nCount = m_ctrlHostList.GetItemCount(); LVHITTESTINFO ht; ht.pt = pNM->ptAction; m_ctrlHostList.SubItemHitTest(&ht); if (ht.iItem < 0 || ht.iItem > nCount) { int nItem = GetSelectedItem(); m_ctrlHostList.SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED); } else { m_ctrlHostList.SetItemState(ht.iItem, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED); } *pResult = 0; }
This causes the last item to be selected in the list if the user clicks in the empty area of the control. What a pain in the ass... ------- signature starts "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001 Please review the Legal Disclaimer in my bio. ------- signature ends -
These aren't problems with
CListCtrl
per se, but the Windows list-view control underneath, which is an A-number-1 mother-batch when it comes to handling selections. The essence of modifying the selection behavior is to handle theLVN_ITEMCHANGING
andLVN_ITEMCHANGED
notifications.LVN_ITEMCHANGING
lets you decide whether or not to permit a state change in a list view item. In this case, you could find out where the user clicked and use that to make the decision.LVN_ITEMCHANGED
tells you after an item's state changed.
Software Zen:
delete this;
Hello, Thanks for the info but can't we achieve this using a OnItemchangingMyList function ? :
void CSQLiteAddressBookDlg::OnItemchangingListContacts(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; // return FALSE (or 0) to allow change, TRUE to prevent // http://www.celticwolf.com/FAQs/CListCtrl_FAQ.html *pResult = 0; }
As specified in the Celtic Wolf FAQ, I should affect FALSE or 0 to pResult in order to cancel the selection change. But it doesn't work. I even tried to use OnNotify but can't find a way to make it work. It seems events LVN_ITEMCHANGED or LVN_ITEMCHANGING never occur.BOOL CSQLiteAddressBookDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { switch (wParam) { case IDC_LIST_CONTACTS: { LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam; switch (pnmv->lParam) { case LVN_ITEMCHANGED: { TRACE0 ("LVN_ITEMCHANGING\n"); break; } case LVN_ITEMCHANGING: { ... break; } } break; } } return CDialog::OnNotify(wParam, lParam, pResult); }
I checked codeproject tutorials and can't find anything about using OnNotify with List controls. Thanks, JM Earth > Europe > France > Lyon