How to detect a CListCtrl selection change?
Asked Answered
S

4

37

I want to execute some code when the user selects a row in a CListCtrl (report view, I don't care about the other viewing modes).

How do I catch this event? is there some message I can map or a method like "OnSelectionChanged" or something like that?

Speleology answered 22/9, 2009 at 22:10 Comment(0)
G
52

Also try:

BEGIN_MESSAGE_MAP(cDlgRun, CDialog)
    ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST2, OnItemchangedList2)
END_MESSAGE_MAP()

/* ... */

void cDlgRun::OnItemchangedList2(NMHDR* pNMHDR, LRESULT* pResult) 
{
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

    if ((pNMListView->uChanged & LVIF_STATE) 
        && (pNMListView->uNewState & LVIS_SELECTED))
    {
        // do stuff...
    }
}
Garofalo answered 23/9, 2009 at 13:40 Comment(5)
This will not catch a change when you select three elements with shift, but then select any of them (which deselects the other two, but keeps this one selected). Any workaround for that except keeping a list of selected items?Lay
I cannot test it right now but I think you will need to catch deselection as well as selection: to catch deselection just use if ((pNMListView->uChanged & LVIF_STATE) && (pNMListView->uOldState & LVNI_SELECTED) && !(pNMListView->uNewState & LVNI_SELECTED))Garofalo
@djeidot: Thank you very much, it helped. When embedded in its own Control class, this could aso be reduced to ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, &OnItemSelected)Mindi
@LS_dev don't worry, I'm sure it works. À confiança.Garofalo
The pNMListView->uChanged & LVIF_STATE condition is very important, because if you don't check, it will do things on undesired moments; in my case i had this triggering when I was doing SetItemTextQualifier
L
15

There are a few notifications based on what's happening.

If you are selecting an item and nothing is selected yet, you will get one LVIF_STATE change notification: uNewState & LVIS_SELECTED. The newly selected item will be found at:

pNMListView->iItem

If an item is selected before you select a new object, you'll get three state changes:

First you will be informed that the previous item in focus is losing focus:

pNMListView->uOldState & LVIS_FOCUSED

Then you will be notified that the old item is being unselected:

pNMListView->uOldState & LVIS_SELECTED

Finally, you will get the new item selection state:

pNMListView->uNewState & LVIS_SELECTED

(again look at iItem for newly selected item)

So the pitfall we ran across is that, because item deselection results in two notifications, we were doing a lot of repetitive, sometimes detrimental, processing. What we ended up doing was only doing this processing for the 2nd message (pNMListView->uOldState & LVIS_SELECTED), and skipping the same processing after the loss of focus notification.

Linell answered 19/10, 2012 at 18:15 Comment(1)
Great explanation! It's important to know why the function handling LVN_ITEMCHANGED is called multiple times. And interesting that the states LVIS_FOCUSED and LVIS_SELECTED from the previous item are manipulated separatelyLizbeth
R
4

djeidot is right on.

I just want to add that there is no OnSelectionChanged() because the ListView supports multi-selection (although this can be disabled). Therefore, a single-selection listview will send you two events: Old item unselected AND New item selected.

Rebarbative answered 25/9, 2009 at 15:16 Comment(0)
F
0

On my Visual Studio 2010, the visual editor declares a callback in the dialog header file like this:

afx_msg void OnLbnSelchangeListOnvif();

and in the source file:

BEGIN_MESSAGE_MAP(CDialogOnvif, CDialog)
    ON_LBN_SELCHANGE(IDC_LIST_ONVIF, &CDialogOnvif::OnLbnSelchangeListOnvif)
END_MESSAGE_MAP()

void CDialogOnvif::OnLbnSelchangeListOnvif()
{
    // do stuff...
}
Flagella answered 30/6, 2014 at 13:30 Comment(1)
That will only work for List Boxes (CListBox), not CListCtrl.Mind

© 2022 - 2024 — McMap. All rights reserved.