Numéro d'article: 250614 - Dernière mise à jour: mardi 21 novembre 2006 - Version: 1.2

Comment faire pour trier les éléments dans un CListCtrl dans l'affichage de rapport

A noterCet article s'applique à un système d'exploitation différent de celui que vous utilisez. Le contenu de l'article qui ne vous concerne peut-être pas est désactivé.
Agrandir tout | Réduire tout

Résumé

Pas beaucoup d'informations a été fourni pour le processus de tri des éléments dans un contrôle ListView, en particulier une encapsulé par la classe MFC CListCtrl. Les détails sont faciles à implémenter et cet article tente de remplir l'espace dans la documentation pour cette fonctionnalité utile. L'exemple de code représente une boîte de dialogue MFC avec un contrôle de liste défini pour le style LVS_REPORT.

Plus d'informations

Pour trier les éléments dans un contrôle ListView, il doit y avoir une structure LVITEM associée à l'élément. MFC fournit ce pour les développeurs, permettant à un élément à insérer par un appel de fonction InsertItem(int nItem, LPCTSTR lpszItem) simple qui crée la structure avec les valeurs par défaut raisonnables. Telle une mémoire tampon à partir de la complexité sous-jacente peut parfois être trompeur. Toutefois, la structure LVITEM est une clé importante pour manipuler des éléments ListView, y compris le mécanisme de tri.

L'élément lParam du LVITEM fournit les informations nécessaires. Lorsque la fonction SortItems de la classe CListCtrl est appelée, elle doit fournir un pointeur fonction vers une fonction de rappel de tri et une valeur DWORD définie par l'application. Pendant le tri, la fonction de rappel est appelée à plusieurs reprises que deux éléments du contrôle de liste sont sélectionnés pour la comparaison. Les paramètres qu'il reçoit constituent l'élément lParam à partir LVITEM structure de chaque élément et la valeur DWORD passé par l'appel SortItems.

Le code ci-dessous représente un exemple simple de tri d'une liste des présidents de dix américain dans un contrôle ListView. Les présidents sont initialement stockés dans un tableau statique de CString multidimensionnel.

static CString strData[10][3] =
{
	{ _T("Washington"), _T("George"), _T("1789-1797") },
	{ _T("Adams"), _T("John"), _T("1797-1801") },
	{ _T("Jefferson"), _T("Thomas"), _T("1801-1809") },
	{ _T("Madison"), _T("James"), _T("1809-1817") },
	{ _T("Monroe"), _T("James"), _T("1817-1825") },
	{ _T("Adams"), _T("John Quincy"), _T("1825-1829") },
	{ _T("Jackson"), _T("Andrew"), _T("1829-1837") },
	{ _T("Van Buren"), _T("Martin"), _T("1837-1841") },
	{ _T("Harrison"), _T("William Henry"), _T("1841") },
	{ _T("Tyler"), _T("John"), _T("1841-1845") }
};
				

La fonction de tri de rappel peut être définie statiquement en tant que membre d'une classe ou, comme ici, simplement comme fonction globale :
int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
				

L'élément lParam peut s'agir de simple à très complexes. Fréquemment, une structure est utile dans ce contexte, permettant à plusieurs éléments de données à référencer. Par exemple, une structure appelée ITEMDATA a été définie pour contenir les trois éléments comprenant un élément donné :
typedef struct {
	LPTSTR pszLastName;
	LPTSTR pszFirstName;
	LPTSTR pszTerm;
} ITEMDATA, *PITEMDATA;
				

Dans cet exemple, la structure a été définie dans fichier d'en-tête d'une classe CDialog et une variable de membre d'un pointeur vers un tableau de 10 a été définie :
	ITEMDATA* m_pData[10];
				

Un contrôle ListView a été ajouté à une boîte de dialogue et une variable de membre défini par l'appelé m_ctlListView. Ils ont été ajoutés dans OnInitDialog :

	m_ctlListView.InsertColumn(0, _T("Last Name"), LVCFMT_LEFT, 100);
	m_ctlListView.InsertColumn(1, _T("First Name"), LVCFMT_LEFT, 100);
	m_ctlListView.InsertColumn(2, _T("Term"), LVCFMT_LEFT, 100);

	for (int i=0; i<10; i++)
	{
		m_pData[i] = new ITEMDATA;
		m_pData[i]->pszLastName = (LPTSTR)(LPCTSTR)strData[i][0];
		m_pData[i]->pszFirstName = (LPTSTR)(LPCTSTR)strData[i][1];
		m_pData[i]->pszTerm = (LPTSTR)(LPCTSTR)strData[i][2];

		m_ctlListView.InsertItem(i, strData[i][0]);
		m_ctlListView.SetItemText(i, 1, strData[i][1]);
		m_ctlListView.SetItemText(i, 2, strData[i][2]);
		m_ctlListView.SetItemData(i, (LPARAM)m_pData[i]);
	}
				

Trois colonnes ont été insérés pour le dernier nom, prénom et durée du mandat. Ensuite, pour chacune des dix éléments, une nouvelle structure ITEMDATA est allouée et initialisée à partir du tableau de CString. L'élément est inséré très simplement, à l'aide uniquement l'index et de la dernière chaîne de nom, puis le texte est défini pour les deux autres colonnes de l'élément. Enfin, la fonction SetItemData est appelée, en passant le ITEMDATA nouvelle en tant que paramètre. Ceci réinitialise le lParam de la structure de l'article LVITEM et prépare la façon dont le tri.

Les MFC dans Visual C++ 6.0 a un problème avec des notifications d'en-tête pour le contrôle ListView. Bien qu'un gestionnaire peut être ajouté, dans la version actuelle il n'est pas appelé. Utilisez par exemple, Assistant classe ou la barre Assistant pour ajouter un gestionnaire de messages Windows. Si l'ID du contrôle ListView est en surbrillance, un nombre de messages de notification est disponible pour sélection. Pour trier les éléments lorsqu'un clic est effectué sur l'en-tête pour une colonne donnée, sélectionnez la notification HDN_ITEMCLICK. Une entrée de la table des messages ON_NOTIFY est générée, mais aussi une fonction gestionnaire. Par exemple en cours, l'entrée apparaît comme suit :

	ON_NOTIFY(HDN_ITEMCLICK, IDC_LIST1, OnItemclickList1)
				

Le problème ici est que la notification n'est pas proviennent en fait le contrôle ListView ; au lieu de cela, le contrôle d'en-tête créé par le ListView envoie la notification. L'entrée de la table des messages répertoriée ci-dessus ne fonctionne pas. La solution est simple, cependant, dans la mesure où le contrôle d'en-tête a toujours une valeur d'ID de 0, la macro peut être modifiée pour fonctionner correctement :
	ON_NOTIFY(HDN_ITEMCLICK, 0, OnItemclickList1)
				

Puis, dans le Gestionnaire OnItemclickList1, l'appel SortItems est effectué :
void CSortListDlg::OnItemclickList1(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NMLISTVIEW *pLV = (NMLISTVIEW *) pNMHDR;
	
	m_ctlListView.SortItems(SortFunc, pLV->iItem);
	
	*pResult = 0;
}
				

L'en-tête de message de notification (NMHDR) est en fait une notification de ListView, NMLISTVIEW, qui contient l'index de la colonne sur laquelle l'utilisateur a cliqué. Dans cet exemple, il est représenté par iItem. Listes plus complexes devrez référencer l'élément iSubItem de cette structure également. L'adresse de la fonction de rappel est passée à SortItems, ainsi que le numéro de colonne qui a été activé.

La routine SortFunc est appelée à plusieurs reprises que les paires d'éléments de ListView sont passées à la fonction de comparaison. Les deux premiers paramètres sont l'élément de lParam de structure LVITEM les éléments de respectifs et le troisième paramètre (défini par l'application) est le numéro de la colonne dans l'appel SortItems.
int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	int nRetVal;

	PITEMDATA pData1 = (PITEMDATA)lParam1;
	PITEMDATA pData2 = (PITEMDATA)lParam2;


	switch(lParamSort)
	{
	case 0:	// Last Name
		nRetVal = strcmp(pData1->pszLastName,
                                 pData2->pszLastName);
		break;

	case 1:	// First Name
		nRetVal = strcmp(pData1->pszFirstName,
                                 pData2->pszFirstName);
		break;

	case 2: // Term
		nRetVal = strcmp(pData1->pszTerm, pData2->pszTerm);
		break;

	default:
		break;
	}

	return nRetVal;
}
				

L'index de colonne passé lParamSort détermine quel élément des objets ITEMDATA passé dans lParam1 et lParam2 doit être utilisé pour la comparaison. Le résultat est renvoyé et le processus continue jusqu'à ce que tous les éléments ont été triées.

En tant qu'un rappel, les structures ITEMDATA qui ont été attribués pour les éléments de liste devez finit par être détruits. Par exemple, le gestionnaire WM_DESTROY pour la boîte de dialogue parcourt les éléments de membre et les supprime.
	for (int i=0; i<10; i++)
		delete m_pData[i];
				

Références

Pour plus d'informations sur le contrôle commun de ListView, consultez la documentation Du Kit de développement Platform SDK sous Contrôles communs Windows dans la section Services d'interface utilisateur.

Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft Foundation Class Library 4.2
Mots-clés : 
kbmt kbcmnctrls kbctrl kbhowto kblistview KB250614 KbMtfr
Traduction automatiqueTraduction automatique
IMPORTANT : Cet article est issu du système de traduction automatique mis au point par Microsoft (http://support.microsoft.com/gp/mtdetails). Un certain nombre d?articles obtenus par traduction automatique sont en effet mis à votre disposition en complément des articles traduits en langue française par des traducteurs professionnels. Cela vous permet d?avoir accès, dans votre propre langue, à l?ensemble des articles de la base de connaissances rédigés originellement en langue anglaise. Les articles traduits automatiquement ne sont pas toujours parfaits et peuvent comporter des erreurs de vocabulaire, de syntaxe ou de grammaire (probablement semblables aux erreurs que ferait une personne étrangère s?exprimant dans votre langue !). Néanmoins, mis à part ces imperfections, ces articles devraient suffire à vous orienter et à vous aider à résoudre votre problème. Microsoft s?efforce aussi continuellement de faire évoluer son système de traduction automatique.
La version anglaise de cet article est la suivante: 250614  (http://support.microsoft.com/kb/250614/en-us/ )
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.
Retired KB ArticleExclusion de responsabilité concernant les contenus obsolètes dans la Base de connaissances
Cet article concerne des produits pour lesquels Microsoft n'offre plus de support. Il est par conséquent fourni « en l'état » et ne sera plus mis à jour.