À propos des contrôles d’en-tête

Un contrôle d’en-tête est une fenêtre qui est généralement positionnée au-dessus des colonnes de texte ou de nombres. Il contient un titre pour chaque colonne et peut être divisé en parties. L’utilisateur peut faire glisser les séparateurs qui séparent les parties pour définir la largeur de chaque colonne. L’illustration suivante montre un contrôle d’en-tête qui a étiqueté des colonnes qui fournissent des informations détaillées sur les fichiers d’un répertoire.

capture d’écran d’une boîte de dialogue avec un contrôle d’en-tête à trois colonnes

Vous pouvez créer un contrôle d’en-tête à l’aide de la fonction CreateWindowEx , en spécifiant la classe de fenêtre WC_HEADER et les styles de contrôle d’en-tête appropriés. Cette classe de fenêtre est inscrite lors du chargement de la DLL de contrôle commun. Pour vous assurer que cette DLL est chargée, utilisez la fonction InitCommonControlsEx . Après avoir créé un contrôle d’en-tête, vous pouvez le diviser en parties, définir le texte dans chaque partie et contrôler l’apparence de la fenêtre à l’aide de messages de fenêtre d’en-tête.

Un contrôle d’en-tête peut être créé en tant que fenêtre enfant d’un autre contrôle, tel qu’une zone de liste. Toutefois, le contrôle parent ne connaît pas le contrôle d’en-tête et n’autorise pas l’espace occupé par l’en-tête, ce qui entraîne l’affichage des éléments de liste derrière l’en-tête. Si vous souhaitez utiliser un contrôle d’en-tête dans une zone de liste ou un autre contrôle, le contrôle parent doit être dessiné par le propriétaire afin que tous les éléments soient affichés à la bonne position.

Les contrôles d’affichage de liste ont déjà des contrôles d’en-tête. Au lieu de créer un contrôle d’en-tête pour un contrôle d’affichage de liste, vous utilisez LVM_GETHEADER ou ListView_GetHeader pour récupérer le contrôle existant.

Taille et position du contrôle d’en-tête

En règle générale, vous devez définir la taille et la position d’un contrôle d’en-tête pour qu’ils s’inscrivent dans les limites d’un rectangle particulier, par exemple la zone cliente d’une fenêtre. En utilisant le message HDM_LAYOUT , vous pouvez récupérer les valeurs de taille et de position appropriées à partir du contrôle d’en-tête.

Lors de l’envoi d’HDM_LAYOUT, vous spécifiez l’adresse d’une structure HDLAYOUT qui contient les coordonnées du rectangle que le contrôle d’en-tête doit occuper et fournit un pointeur vers une structure WINDOWPOS . Le contrôle remplit la structure WINDOWPOS avec des valeurs de taille et de position appropriées pour positionner le contrôle en haut du rectangle spécifié. La valeur height correspond à la somme des hauteurs des bordures horizontales du contrôle et de la hauteur moyenne des caractères de la police actuellement sélectionnée dans le contexte d’appareil du contrôle.

Si vous souhaitez utiliser HDM_LAYOUT pour définir la taille et la position initiales d’un contrôle d’en-tête, définissez l’état de visibilité initial du contrôle afin qu’il soit masqué. Après avoir envoyé HDM_LAYOUT pour récupérer les valeurs de taille et de position, vous pouvez utiliser la fonction SetWindowPos pour définir le nouvel état de taille, de position et de visibilité.

Éléments

Un contrôle d’en-tête comporte généralement plusieurs éléments d’en-tête qui définissent les colonnes du contrôle. Vous ajoutez un élément à un contrôle d’en-tête en envoyant le message HDM_INSERTITEM au contrôle. Le message inclut l’adresse d’une structure HDITEM . Cette structure définit les propriétés de l’élément d’en-tête, qui peuvent inclure une chaîne, une image bitmap, une taille initiale et une valeur LPARAM définie par l’application.

Le membre fmt de la structure HDITEM d’un élément peut inclure l’indicateur HDF_STRING ou HDF_BITMAP pour indiquer si le contrôle affiche la chaîne ou la bitmap de l’élément. Si vous souhaitez afficher à la fois une chaîne et une bitmap, créez un élément dessiné par le propriétaire en définissant le membre fmt de manière à inclure l’indicateur HDF_OWNERDRAW . La structure HDITEM spécifie également des indicateurs de mise en forme qui indiquent au contrôle s’il faut centrer, aligner à gauche ou aligner à droite la chaîne ou la bitmap dans le rectangle de l’élément.

HDM_INSERTITEM retourne l’index de l’élément nouvellement ajouté. Vous pouvez utiliser l’index dans d’autres messages pour définir des propriétés ou récupérer des informations sur l’élément. Vous pouvez supprimer un élément à l’aide du message HDM_DELETEITEM , en spécifiant l’index de l’élément à supprimer.

Vous pouvez utiliser le message HDM_SETITEM pour définir les propriétés d’un élément d’en-tête existant et le message HDM_GETITEM pour récupérer les propriétés actuelles d’un élément. Pour récupérer le nombre d’éléments d’un contrôle d’en-tête, utilisez le message HDM_GETITEMCOUNT .

contrôles d’en-tête Owner-Drawn

Vous pouvez définir des éléments individuels d’un contrôle d’en-tête comme des éléments dessinés par le propriétaire. L’utilisation de cette technique vous donne plus de contrôle que vous n’en auriez autrement sur l’apparence d’un élément d’en-tête.

Vous pouvez utiliser le message HDM_INSERTITEM pour insérer un nouvel élément dessiné par le propriétaire dans un contrôle d’en-tête ou le message HDM_SETITEM pour remplacer un élément existant par un élément dessiné par le propriétaire. Les deux messages incluent l’adresse d’une structure HDITEM , dont le membre fmt doit être défini sur la valeur HDF_OWNERDRAW .

Lorsqu’un contrôle d’en-tête doit dessiner un élément dessiné par le propriétaire, il envoie le message WM_DRAWITEM à la fenêtre parente. Le paramètre wParam du message est l’identificateur de fenêtre enfant du contrôle d’en-tête, et le paramètre lParam est l’adresse d’une structure DRAWITEMSTRUCT . La fenêtre parente utilise les informations de la structure pour dessiner l’élément. Pour un élément dessiné par le propriétaire dans un contrôle d’en-tête, la structure DRAWITEMSTRUCT contient les informations suivantes.

Membre Description
CtlType ODT_HEADER type de contrôle dessiné par le propriétaire.
CtlID Identificateur de fenêtre enfant du contrôle d’en-tête.
Itemid Index de l’élément à dessiner.
itemAction ODA_DRAWENTIRE’indicateur d’action de dessin.
itemState ODS_SELECTED indicateur d’action de dessin si le curseur se trouve sur l’élément et que le bouton de la souris est vers le bas. Sinon, ce membre est égal à zéro.
hwndItem Gérez le contrôle d’en-tête.
Hdc Gérez le contexte de l’appareil du contrôle d’en-tête.
rcItem Coordonnées de l’élément d’en-tête à dessiner. Les coordonnées sont relatives à l’angle supérieur gauche du contrôle d’en-tête.
itemData Valeur 32 bits définie par l’application associée à l’élément.

 

Filtres de contrôle d’en-tête

En spécifiant le style de fenêtre HDS_FILTERBAR pour un contrôle d’en-tête, vous pouvez activer le placement des zones d’édition de filtre sous les en-têtes de colonne. Un bouton de filtre s’affiche en regard de la zone d’édition. Vous pouvez implémenter le filtrage en répondant aux codes de notification HDN_BEGINFILTEREDIT, HDN_ENDFILTEREDIT, HDN_FILTERBTNCLICK ou HDN_FILTERCHANGE .

Par défaut, la zone d’édition contient une invite permettant à l’utilisateur d’entrer du texte. Vous pouvez restaurer la zone d’édition à cet état par défaut en utilisant Header_ClearFilter ou Header_ClearAllFilters.

L’exemple de code suivant montre comment récupérer le contrôle d’en-tête à partir d’un contrôle d’affichage de liste et ajouter une barre de filtre.

// hList is the HWND of the list-view control.
HWND hHeader = ListView_GetHeader(hList);
LONG_PTR styles = GetWindowLongPtr(hHeader, GWL_STYLE);
SetWindowLongPtr(g_hHeader, GWL_STYLE, styles | HDS_FILTERBAR);

Traitement des messages de contrôle d’en-tête par défaut

Cette section décrit les messages de fenêtre gérés par la procédure de fenêtre pour la classe de fenêtre WC_HEADER .

Message Traitement effectué
WM_CREATE Initialise le contrôle d’en-tête.
WM_DESTROY Annule l’initialisation du contrôle d’en-tête.
WM_ERASEBKGND Remplit l’arrière-plan du contrôle d’en-tête à l’aide de la couleur d’arrière-plan actuelle du contrôle.
WM_GETDLGCODE Retourne une combinaison des valeurs DLGC_WANTTAB et DLGC_WANTARROWS .
WM_GETFONT Retourne le handle à la police actuelle, qui est utilisée par le contrôle d’en-tête pour dessiner son texte.
WM_LBUTTONDBLCLK Capture l’entrée de la souris. Si le curseur de la souris se trouve sur un séparateur, le contrôle envoie le code de notification HDN_BEGINTRACK et commence à faire glisser le séparateur. Si le curseur se trouve sur un élément, l’élément est affiché dans l’état enfoncé.
WM_LBUTTONDOWN Identique au message WM_LBUTTONDBLCLK .
WM_LBUTTONUP Libère la capture de la souris. Si le contrôle faisait le suivi du mouvement de la souris, il envoie le code de notification HDN_ENDTRACK et redessine le contrôle d’en-tête. Sinon, le contrôle envoie le code de notification HDN_ITEMCLICK et redessine l’élément d’en-tête sur lequel on a cliqué.
WM_MOUSEMOVE Si un séparateur est déplacé, le contrôle envoie le code de notification HDN_TRACK et affiche l’élément à la nouvelle position. Si le bouton gauche de la souris est enfoncé et que le curseur se trouve sur un élément, l’élément est affiché dans l’état appuyé.
WM_NCCREATE Alloue et initialise une structure de données interne.
WM_NCDESTROY Libère les ressources allouées par le contrôle d’en-tête une fois le contrôle d’en-tête non initialisé.
WM_PAINT Peint la région non valide du contrôle d’en-tête. Si le paramètre wParam n’est pas NULL, le contrôle suppose que la valeur est un HDC et peint à l’aide de ce contexte d’appareil.
WM_SETCURSOR Définit la forme du curseur, selon que le curseur se trouve sur un séparateur ou dans un élément d’en-tête.
WM_SETFONT Sélectionne un nouveau handle de police dans le contexte de l’appareil pour le contrôle d’en-tête.