2
votes

I'm writing a dialog based MFC application on Visual Studio 2017 in C++.

In the dialog I have a list control. I want to know which column the user changes if he edits the list.

the list control looks like this:

enter image description here

So if I edit the cell Channel Mode B I expect the value of the cell to be row = 2 and col = 1. I've tried using the following code:

In the mask field of LVCOLUMN I've enabled the following flag:

LVCOLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;

In the MESSAGE_MAP I've added the following notification:

ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, &CEditableListControlDlg::OnLvnItemchangedList1)

and the handler I've written is:

void CEditableListControlDlg::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    
    
    
    if (pNMLV->uChanged & LVIF_STATE)
    {
        
        if ((pNMLV->uNewState) & LVIS_SELECTED)
        {
            int iItem = pNMLV->iItem;
            int subItem = pNMLV->iSubItem;
        }
    }
    *pResult = 0;
}

In this code the variable iItem is the row selected and subItem is the column selected. What interests me is to get the pNMLV->iSubItem. My problem is that the value of the subItem variable is always zero, which mean it hasn't been selected by Microsoft Docs Documentation here

How can I get the index of the sub-item which been edited?

Thank you.

1
What's the rationale behind abusing the list control like this? The information you are trying to represent really wants an array of check boxes. Those are switches the user can toggle, which is the most natural way to describe the data.IInspectable

1 Answers

2
votes

When you select a different line, the message will respond. If you select the same row and different columns, the message will not respond repeatedly. So, the iSubItem will be always 0 when you only change the column.

You could refer to the following example.

void CSdfsdfDlg::OnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult) 
{
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    // TODO: Add your control notification handler code here
     
    if ((pNMListView-> uChanged   &   LVIF_STATE)   &&   (pNMListView-> uNewState   &   LVIS_SELECTED)) 
    {
        DWORD   dwPos =GetMessagePos(); 
        CPoint   point(LOWORD(dwPos),HIWORD(dwPos)); 
         
        m_lst.ScreenToClient(&point);   
         
        LVHITTESTINFO lvinfo; 
        lvinfo.pt = point; 
        lvinfo.flags = LVHT_ABOVE; 
         
        int  nItem = m_lst.SubItemHitTest(&lvinfo); 
        if(nItem!=-1) 
        { 
            CString strtemp; 
            strtemp.Format( "the row is %d and the column is %d ", lvinfo.iItem, lvinfo.iSubItem); 
            MessageBox(strtemp);
        } 
         
    }
 
 
    *pResult = 0;
}