2009-09-22 10 views
27

Quiero ejecutar algún código cuando el usuario selecciona una fila en un CListCtrl (vista de informe, no me importan los otros modos de visualización).¿Cómo detectar un cambio en la selección de CListCtrl?

¿Cómo puedo ver este evento? ¿Hay algún mensaje que pueda mapear o un método como "OnSelectionChanged" o algo así?

Respuesta

38

Proveedores:

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... 
    } 
} 
+1

Esto no va a coger un cambio cuando selecciona tres elementos con shift, pero luego selecciona cualquiera de ellos (lo que anula la selección de los otros dos, pero mantiene este seleccionado). ¿Alguna solución para eso excepto mantener una lista de elementos seleccionados? –

+0

No puedo probarlo en este momento, pero creo que tendrá que seleccionar deselección así como selección: para atrapar la deselección solo use 'if ((pNMListView-> uChanged & LVIF_STATE) && (pNMListView-> uOldState & LVNI_SELECTED) &&! (PNMListView -> uNewState & LVNI_SELECTED)) ' – djeidot

+2

@djeidot: Muchas gracias, ayudó. Cuando está incrustado en su propia clase de control, esto también puede reducirse a ON_NOTIFY_REFLECT (LVN_ITEMCHANGED, y OnItemSelected) – mox

4

djeidot está justo en.

Solo quiero agregar que no hay OnSelectionChanged() porque ListView admite la selección múltiple (aunque esto se puede deshabilitar). Por lo tanto, una vista de lista de selección única le enviará dos eventos: Artículo anterior no seleccionado Y Nuevo elemento seleccionado.

9

Hay algunas notificaciones basadas en lo que está sucediendo.

Si está seleccionando un elemento y no se ha seleccionado nada aún, recibirá una notificación de cambio LVIF_STATE: uNewState & LVIS_SELECTED. El elemento recién seleccionado se puede encontrar en:

pNMListView->iItem 

Si se selecciona un elemento antes de seleccionar un nuevo objeto, obtendrá tres cambios de estado:

Primero se le informará de que el elemento anterior de el foco está perdiendo el foco:

pNMListView->uOldState & LVIS_FOCUSED 

A continuación, se le notificará que el viejo artículo está siendo seleccionada:

pNMListView->uOldState & LVIS_SELECTED 

Finalmente, obtendrá el nuevo estado de selección de elementos:

pNMListView->uNewState & LVIS_SELECTED 

(de nuevo un vistazo a iItem para el artículo que acaba de seleccionar)

Así la trampa que nos encontramos al otro lado es que, ya que los resultados elemento Desactivar en dos notificaciones , estábamos haciendo un montón de procesamiento repetitivo, a veces perjudicial. Lo que terminamos haciendo fue solo hacer este procesamiento para el segundo mensaje (pNMListView->uOldState & LVIS_SELECTED), y omitir el mismo procesamiento después de la pérdida de la notificación de foco.

-1

En mi Visual Studio 2010, el editor visual declara una devolución de llamada en el archivo de cabecera de diálogo como este:

afx_msg void OnLbnSelchangeListOnvif(); 

y en el archivo de origen:

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

void CDialogOnvif::OnLbnSelchangeListOnvif() 
{ 
    // do stuff... 
} 
+2

Eso solo funcionará para List Box (CListBox), no CListCtrl. –

Cuestiones relacionadas