Comment personnaliser les barres d’outils

La plupart des applications Windows utilisent des contrôles de barre d’outils pour fournir aux utilisateurs un accès pratique aux fonctionnalités du programme. Toutefois, les barres d’outils statiques présentent certaines lacunes, telles que l’espace insuffisant pour afficher efficacement tous les outils disponibles. La solution à ce problème consiste à rendre les barres d’outils de votre application personnalisables par l’utilisateur. Ensuite, les utilisateurs peuvent choisir d’afficher uniquement les outils dont ils ont besoin, et ils peuvent les organiser d’une manière qui correspond à leur style de travail personnel.

Notes

Les barres d’outils dans les boîtes de dialogue ne peuvent pas être personnalisées.

 

Pour activer la personnalisation, incluez l’indicateur de style CCS_ADJUSTABLE contrôles courants lorsque vous créez le contrôle de barre d’outils. Il existe deux approches de base pour la personnalisation :

  • Boîte de dialogue de personnalisation. Cette boîte de dialogue fournie par le système est l’approche la plus simple. Il offre aux utilisateurs une interface utilisateur graphique qui leur permet d’ajouter, de supprimer ou de déplacer des icônes.
  • Glisser-déplacer des outils. L’implémentation de la fonctionnalité glisser-déplacer permet aux utilisateurs de déplacer des outils vers un autre emplacement de la barre d’outils ou de les supprimer en les faisant glisser hors de la barre d’outils. Il offre aux utilisateurs un moyen rapide et simple d’organiser leur barre d’outils, mais ne leur permet pas d’ajouter des outils.

Vous pouvez implémenter l’approche ou les deux, en fonction des besoins de l’application. Aucune de ces deux approches de personnalisation ne fournit un mécanisme intégré, tel qu’un bouton Annuler ou Annuler, pour retourner la barre d’outils à son état antérieur. Vous devez utiliser explicitement l’API de contrôle de barre d’outils pour stocker l’état de précustomisation de la barre d’outils. Si nécessaire, vous pouvez utiliser ultérieurement ces informations stockées pour restaurer la barre d’outils à son état d’origine.

Bon à savoir

Technologies

Prérequis

  • C/C++
  • Programmation de l’interface utilisateur Windows

Instructions

Boîte de dialogue Personnalisation

La boîte de dialogue de personnalisation est fournie par le contrôle de barre d’outils pour donner aux utilisateurs un moyen simple d’ajouter, de déplacer ou de supprimer des outils. Les utilisateurs peuvent le lancer en double-cliquant sur la barre d’outils. Les applications peuvent lancer la boîte de dialogue de personnalisation par programmation en envoyant au contrôle de barre d’outils un message TB_CUSTOMIZE .

L’illustration suivante montre un exemple de boîte de dialogue de personnalisation de la barre d’outils.

capture d’écran d’une fenêtre avec une barre d’outils à trois éléments, et une boîte de dialogue avec des listes des boutons disponibles et actuels de la barre d’outils

Les outils de la zone de liste à droite sont ceux qui se trouvent actuellement dans la barre d’outils. Initialement, cette liste contient les outils que vous spécifiez lors de la création de la barre d’outils. La zone de liste de gauche contient les outils disponibles à ajouter à la barre d’outils. Votre application est chargée de remplir cette liste (autre qu’avec le séparateur, qui apparaît automatiquement).

Le contrôle de barre d’outils avertit votre application qu’elle lance une boîte de dialogue de personnalisation en envoyant à sa fenêtre parente un code de notification TBN_BEGINADJUST suivi d’un code de notification TBN_INITCUSTOMIZE . Dans la plupart des cas, l’application n’a pas besoin de répondre à ces codes de notification. Toutefois, si vous ne souhaitez pas que la boîte de dialogue Personnaliser la barre d’outils affiche un bouton Aide, gérez TBN_INITCUSTOMIZE en retournant TBNRF_HIDEHELP.

Le contrôle de barre d’outils collecte ensuite les informations dont il a besoin pour initialiser la boîte de dialogue en envoyant trois séries de codes de notification, dans l’ordre suivant :

  • Une TBN_QUERYINSERT code de notification pour chaque bouton de la barre d’outils afin de déterminer où les boutons peuvent être insérés. Retournez FALSE pour empêcher l’insertion d’un bouton à gauche du bouton spécifié dans le message de notification. Si vous retournez FALSE à tous les codes de notification TBN_QUERYINSERT, la boîte de dialogue ne s’affiche pas.
  • Une TBN_QUERYDELETE code de notification pour chaque outil qui se trouve actuellement dans la barre d’outils. Retourne TRUE si un outil peut être supprimé, ou FALSE si ce n’est pas le cas.
  • Une série de codes de notification TBN_GETBUTTONINFO pour remplir la liste des boutons disponibles. Pour ajouter un bouton à la liste, renseignez la structure NMTOOLBAR qui est passée avec le code de notification et retournez TRUE. Lorsque vous n’avez plus d’outils à ajouter, retournez FALSE. Notez que vous pouvez retourner des informations pour les boutons qui se trouvent déjà dans la barre d’outils ; ces boutons ne seront pas ajoutés à la liste.

La boîte de dialogue s’affiche ensuite et l’utilisateur peut commencer à personnaliser la barre d’outils.

Lorsque la boîte de dialogue est ouverte, votre application peut recevoir divers codes de notification, en fonction des actions de l’utilisateur :

  • TBN_QUERYINSERT. L’utilisateur a modifié l’emplacement d’un outil dans la barre d’outils ou ajouté un outil. Retournez FALSE pour empêcher l’insertion de l’outil à cet emplacement.
  • TBN_DELETINGBUTTON. L’utilisateur est sur le point de supprimer un outil de la barre d’outils.
  • TBN_CUSTHELP. L’utilisateur a cliqué sur le bouton Aide.
  • TBN_TOOLBARCHANGE. L’utilisateur a ajouté, déplacé ou supprimé un outil.
  • TBN_RESET. L’utilisateur a cliqué sur le bouton Réinitialiser.

Une fois la boîte de dialogue détruite, votre application reçoit un code de notification TBN_ENDADJUST .

L’exemple de code suivant montre une façon d’implémenter la personnalisation de la barre d’outils.

// The buttons are stored in an array of TBBUTTON structures. 
//
// Constants such as STD_FILENEW are identifiers for the 
// built-in bitmaps that have already been assigned as the toolbar's 
// image list.
//
// Constants such as IDM_NEW are application-defined command identifiers.

TBBUTTON allButtons[] = 
    {
        { MAKELONG(STD_FILENEW,  ImageListID), IDM_NEW,   TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"New" },
        { MAKELONG(STD_FILEOPEN, ImageListID), IDM_OPEN,  TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Open"},
        { MAKELONG(STD_FILESAVE, ImageListID), IDM_SAVE,  TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Save"},
        { MAKELONG(STD_CUT,      ImageListID), IDM_CUT,   TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Cut" },
        { MAKELONG(STD_COPY,     ImageListID), IDM_COPY,  TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Copy"},
        { MAKELONG(STD_PASTE,    ImageListID), IDM_PASTE, TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Paste"}
    };

// The following appears in the window's message handler.

case WM_NOTIFY: 
    {
        switch (((LPNMHDR)lParam)->code) 
        {
        
        case TBN_GETBUTTONINFO:  
            {
                LPTBNOTIFY lpTbNotify = (LPTBNOTIFY)lParam;

                // Pass the next button from the array. There is no need to filter out buttons
                // that are already used—they will be ignored.
                
                int buttonCount = sizeof(allButtons) / sizeof(TBBUTTON);
                
                if (lpTbNotify->iItem < buttonCount)
                {
                    lpTbNotify->tbButton = allButtons[lpTbNotify->iItem];
                    return TRUE;
                }
                
                else
                
                {
                    return FALSE;  // No more buttons.
                }
            }
            
            break;

            case TBN_QUERYINSERT:
            
            case TBN_QUERYDELETE:
                return TRUE; 
        }
    }

Outils de glisser-déplacer

Les utilisateurs peuvent également réorganiser les boutons d’une barre d’outils en appuyant sur la touche Maj et en faisant glisser le bouton vers un autre emplacement. Le processus glisser-déplacer est géré automatiquement par le contrôle de barre d’outils. Il affiche une image fantôme du bouton à mesure qu’il est déplacé et réorganise la barre d’outils après sa suppression. Les utilisateurs ne peuvent pas ajouter des boutons de cette façon, mais ils peuvent supprimer un bouton en le supprimant hors de la barre d’outils.

Bien que le contrôle de barre d’outils effectue normalement cette opération automatiquement, il envoie également à votre application deux codes de notification : TBN_QUERYDELETE et TBN_QUERYINSERT. Pour contrôler le processus de glisser-déplacer, gérez ces codes de notification comme suit :

  • Le code de notification TBN_QUERYDELETE est envoyé dès que l’utilisateur tente de déplacer le bouton, avant que le bouton fantôme ne s’affiche. Retournez false pour empêcher le déplacement du bouton. Si vous retournez TRUE, l’utilisateur peut déplacer l’outil ou le supprimer en le supprimant de la barre d’outils. Si un outil peut être déplacé, il peut être supprimé. Toutefois, si l’utilisateur supprime un outil, le contrôle de barre d’outils envoie à votre application un code de notification TBN_DELETINGBUTTON , auquel cas vous pouvez choisir de réinsérer le bouton à son emplacement d’origine, annulant ainsi la suppression.
  • Le code de notification TBN_QUERYINSERT est envoyé lorsque l’utilisateur tente de supprimer le bouton dans la barre d’outils. Pour empêcher la suppression du bouton déplacé à gauche du bouton spécifié dans la notification, retournez LA VALEUR FALSE. Ce code de notification n’est pas envoyé si l’utilisateur supprime l’outil de la barre d’outils.

Si l’utilisateur tente de faire glisser un bouton sans appuyer également sur la touche Maj, le contrôle de barre d’outils ne gère pas l’opération glisser-déplacer. Toutefois, il envoie à votre application un code de notification TBN_BEGINDRAG pour indiquer le début d’une opération de glissement, et un code de notification TBN_ENDDRAG pour indiquer la fin. Si vous souhaitez activer cette forme de glisser-déplacer, votre application doit gérer ces codes de notification, fournir l’interface utilisateur nécessaire et modifier la barre d’outils pour refléter les modifications.

Enregistrement et restauration des barres d’outils

Dans le processus de personnalisation d’une barre d’outils, votre application peut avoir besoin d’enregistrer des informations afin que vous puissiez restaurer la barre d’outils à son état d’origine. Pour lancer l’enregistrement ou la restauration d’un état de barre d’outils, envoyez au contrôle de barre d’outils un message TB_SAVERESTORE avec lParam défini sur TRUE. La valeur lParam de ce message spécifie si vous demandez une opération d’enregistrement ou de restauration. Une fois le message envoyé, il existe deux façons de gérer l’opération d’enregistrement/restauration :

  • Avec les contrôles communs versions 4.72 et antérieures, vous devez implémenter un gestionnaire de TBN_GETBUTTONINFO . Le contrôle de barre d’outils envoie ce code de notification pour demander des informations sur chaque bouton lors de sa restauration.
  • La version 5.80 inclut une option d’enregistrement/restauration. Au début du processus, et à mesure que chaque bouton est enregistré ou restauré, votre application reçoit un code de notification TBN_SAVE ou TBN_RESTORE . Pour utiliser cette option, vous devez implémenter des gestionnaires de notification pour fournir les informations bitmap et d’état nécessaires à l’enregistrement ou à la restauration de l’état de la barre d’outils.

Les états de la barre d’outils sont enregistrés dans un flux de données qui se compose de blocs de données définis par l’interpréteur de commandes en alternance avec des blocs de données définies par l’application. Un bloc de données de chaque type est stocké pour chaque bouton, ainsi qu’un bloc facultatif de données globales que les applications peuvent placer au début du flux. Pendant le processus d’enregistrement, votre gestionnaire de TBN_SAVE ajoute les blocs définis par l’application au flux de données. Pendant le processus de restauration, le gestionnaire de TBN_RESTORE lit chaque bloc et fournit à l’interpréteur de commandes les informations dont il a besoin pour reconstruire la barre d’outils.

Comment gérer une notification TBN_SAVE

Le premier code de notification TBN_SAVE est envoyé au début du processus d’enregistrement. Avant l’enregistrement des boutons, les membres de la structure NMTBSAVE sont définis comme indiqué dans le tableau suivant.

Membre Paramètre
iItem –1
cbData Quantité de mémoire nécessaire pour les données définies par l’interpréteur de commandes.
cButtons Nombre de boutons.
Pdata Quantité calculée de mémoire nécessaire pour les données définies par l’application. En règle générale, vous incluez des données globales, plus des données pour chaque bouton. Ajoutez cette valeur à cbData et allouez suffisamment de mémoire à pData pour tout contenir.
pCurrent Premier octet inutilisé dans le flux de données. Si vous n’avez pas besoin d’informations globales dans la barre d’outils, définissez pCurrent = pData afin qu’il pointe vers le début du flux de données. Si vous avez besoin d’informations de barre d’outils globales, stockez-les dans pData, puis définissez pCurrent sur le début de la partie inutilisée du flux de données avant le retour.

 

Si vous souhaitez ajouter des informations de barre d’outils globales, placez-les au début du flux de données. Avancez pCurrent jusqu’à la fin des données globales afin qu’elles pointent vers le début de la partie inutilisée du flux de données, puis retournez.

Après votre retour, l’interpréteur de commandes commence à enregistrer les informations de bouton. Il ajoute les données définies par l’interpréteur de commandes pour le premier bouton à pCurrent , puis avance pCurrent au début de la partie inutilisée.

Une fois chaque bouton enregistré, un code de notification TBN_SAVE est envoyé et NMTBSAVE est retourné avec ces membres définis comme suit.

Membre Paramètre
iItem Index de base zéro du numéro de bouton.
pCurrent Pointeur vers le premier octet inutilisé dans le flux de données. Si vous souhaitez stocker des informations supplémentaires sur le bouton, stockez-les à l’emplacement pointé par pCurrent et mettez à jour pCurrent pour qu’il pointe ensuite vers la première partie inutilisée du flux de données.
TBBUTTON Structure TBBUTTON qui décrit le bouton en cours d’enregistrement.

 

Lorsque vous recevez le code de notification, vous devez extraire toutes les informations spécifiques au bouton dont vous avez besoin à partir de TBBUTTON. N’oubliez pas que lorsque vous ajoutez un bouton, vous pouvez utiliser le membre dwData de TBBUTTON pour stocker des données spécifiques à l’application. Chargez vos données dans le flux de données sur pCurrent. Avancez pCurrent jusqu’à la fin de vos données, en pointant à nouveau vers le début de la partie inutilisée du flux, puis retournez.

L’interpréteur de commandes passe ensuite au bouton suivant, ajoute ses informations à pData, avance pCurrent, charge TBBUTTON et envoie un autre TBN_SAVE code de notification. Ce processus se poursuit jusqu’à ce que tous les boutons soient enregistrés.

Restauration des barres d’outils enregistrées

Le processus de restauration inverse essentiellement le processus d’enregistrement. Au début, votre application reçoit un code de notification TBN_RESTORE avec le membre iItem de la structure NMTBRESTORE défini sur –1. Le membre cbData a la taille de pData et cButtons est défini sur le nombre de boutons.

Votre gestionnaire de notifications doit extraire les informations globales qui ont été placées au début de pData pendant l’enregistrement, puis avancer pCurrent au début du premier bloc de données définies par l’interpréteur de commandes. Définissez cBytesPerRecord sur la taille des blocs de données que vous avez utilisés pour enregistrer les données du bouton. Définissez cButtons sur le nombre de boutons et retournez.

Le NMTBRESTORE suivant concerne le premier bouton. Le membre pCurrent pointe vers le début de votre premier bloc de données de bouton, et iItem est défini sur l’index de bouton. Extrayez ces données et avancez pCurrent. Chargez les données dans TBBUTTON et retournez. Pour omettre un bouton de la barre d’outils restaurée, définissez le membre idCommand de TBBUTTON sur zéro. L’interpréteur de commandes répète le processus pour les boutons restants. En plus des messages NMTBSAVE et NMTBRESTORE , vous pouvez également utiliser des messages tels que TBN_RESET pour enregistrer et restaurer une barre d’outils.

L’exemple de code suivant enregistre une barre d’outils avant d’être personnalisée et la restaure si l’application reçoit un message TBN_RESET .

int               i;
LPNMHDR           lpnmhdr;
static int        nResetCount;
static LPTBBUTTON lpSaveButtons;
LPARAM            lParam;

switch( lpnmhdr->code)
{
    case TBN_BEGINADJUST: // Begin customizing the toolbar.
    {
        LPTBNOTIFY  lpTB = (LPTBNOTIFY)lparam;
       
        // Allocate memory for the button information.
        
        nResetCount   = SendMessage(lpTB->hdr.hwndFrom, TB_BUTTONCOUNT, 0, 0);
        lpSaveButtons = (LPTBBUTTON)GlobalAlloc(GPTR, sizeof(TBBUTTON) * nResetCount);
      
        // In case the user presses reset, save the current configuration 
        // so the original toolbar can be restored.
        
        for(i = 0; i < nResetCount; i++)
        {
            SendMessage(lpTB->hdr.hwndFrom, 
                        TB_GETBUTTON, i, 
                        (LPARAM)(lpSaveButtons + i));
        }
    }
    
    return TRUE;
   
    case TBN_RESET:
    {
        LPTBNOTIFY lpTB = (LPTBNOTIFY)lparam;
        
        int nCount, i;
    
        // Remove all of the existing buttons, starting with the last one.
        
        nCount = SendMessage(lpTB->hdr.hwndFrom, TB_BUTTONCOUNT, 0, 0);
        
        for(i = nCount - 1; i >= 0; i--)
        {
            SendMessage(lpTB->hdr.hwndFrom, TB_DELETEBUTTON, i, 0);
        }
      
        SendMessage(lpTB->hdr.hwndFrom,      // Restore the saved buttons.
                    TB_ADDBUTTONS, 
                    (WPARAM)nResetCount, 
                    (LPARAM)lpSaveButtons);
    }
    
    return TRUE;
   
    case TBN_ENDADJUST:                // Free up the memory you allocated.
        GlobalFree((HGLOBAL)lpSaveButtons);
        
        return TRUE;
}

Utilisation des contrôles de barre d’outils

Valeurs d’index d’image de bouton standard de la barre d’outils

Démonstration des contrôles communs Windows (CppWindowsCommonControls)