2009-09-22 9 views
27

Je veux exécuter du code lorsque l'utilisateur sélectionne une ligne dans un CListCtrl (vue de rapport, je ne me soucie pas des autres modes de visualisation).Comment détecter un changement de sélection CListCtrl?

Comment attraper cet événement? Y at-il un message que je peux mapper ou une méthode comme "OnSelectionChanged" ou quelque chose comme ça?

Répondre

38

Grossistes:

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

Ce ne sera pas attraper un changement quand vous sélectionnez trois éléments avec décalage, mais sélectionnez-en un (ce qui désélectionne les deux autres, mais garde celui-ci sélectionné). Une solution de contournement pour cela, sauf conserver une liste d'éléments sélectionnés? –

+0

Je ne peux pas le tester maintenant mais je pense que vous aurez besoin d'attraper la désélection ainsi que la sélection: pour attraper la désélection, utilisez 'if ((pNMListView-> uChanged & LVIF_STATE) && (pNMListView-> uOldState & LVNI_SELECTED) &&! (PNMListView -> uNewState & LVNI_SELECTED)) ' – djeidot

+2

@djeidot: Merci beaucoup, ça m'a aidé. Lorsqu'il est intégré dans sa propre classe de contrôle, cela peut aussi être réduit à ON_NOTIFY_REFLECT (LVN_ITEMCHANGED, & OnItemSelected) – mox

4

djeidot est à droite sur.

Je veux juste ajouter qu'il n'y a pas OnSelectionChanged() parce que ListView supporte la multi-sélection (bien que cela puisse être désactivé). Par conséquent, une liste de sélection à sélection unique vous enverra deux événements: Ancien élément non sélectionné ET Nouvel élément sélectionné.

9

Il existe quelques notifications basées sur ce qui se passe.

Si vous sélectionnez un élément et que rien n'est encore sélectionné, vous recevrez une notification de modification LVIF_STATE: uNewState & LVIS_SELECTED. Le nouvel élément sélectionné à l'adresse:

pNMListView->iItem 

Si un élément est sélectionné avant de sélectionner un nouvel objet, vous aurez trois changements d'état:

D'abord, vous serez informé que l'élément précédent mise au point est en train de perdre l'accent:

pNMListView->uOldState & LVIS_FOCUSED 

Ensuite, vous serez informé que l'ancien élément est désélectionné:

pNMListView->uOldState & LVIS_SELECTED 

Enfin, vous obtiendrez le nouvel état de sélection d'article:

pNMListView->uNewState & LVIS_SELECTED 

(regarder à nouveau iItem pour les nouveaux élément sélectionné)

donc le piège que nous avons couru est à travers, parce que les résultats point de désélection dans deux notifications , nous faisions beaucoup de traitement répétitif, parfois préjudiciable. Ce que nous avons fini par faire était seulement de faire ce traitement pour le 2ème message (pNMListView->uOldState & LVIS_SELECTED), et de sauter le même traitement après la notification de perte de focus.

-1

Sur mon Visual Studio 2010, l'éditeur visuel déclare un rappel dans le fichier d'en-tête de dialogue comme celui-ci:

afx_msg void OnLbnSelchangeListOnvif(); 

et dans le fichier source:

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

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

Cela ne fonctionnera que pour les boîtes de liste (CListBox), pas CListCtrl. –

Questions connexes