Barre de status

 

 

Remarque

Il existe une fonction du GDI qui permet d'afficher du texte dans le style de la barre de status: DrawStatusText().

 

Les différents styles de la classe

- Par défaut, la barre de status s'affiche en bas de la fenêtre. Mais il est possible de l'afficher en haut en utilisant CCS_TOP.

- Il est possible d'afficher à gauche de la barre de status un petit dessin représentant la possibilité de changer la taille de la fenêtre. On utilisera alors le style SBARS_SIZEGRIP.

Image non trouvée ! Ne pas utiliser les styles CCS_TOP et SBARS_SIZEGRIP ensemble !

- Enfin, vous pouvez attribuer des tooltips (bulles d'informations) dans les différentes subdivisions de la barre de titre. Mais pour pouvoir faire cela, il faudra autoriser les tooltips en passant SBT_TOOLTIPS. Voir les messages SB_GETTIPTEXT et SB_SETTIPTEXT.

 

Création de l'objet

Avant de créer une barre de status, il faudra s'assurer que la DLL COMCTL32 est chargée. Pour cela, exécutez une seule fois dans votre code la fonction InitCommonControls() ou InitCommonControlsEx().

Vous pourrons donc taper:

- Soit InitCommonControls();

Mais cette commande ne devrait plus être utilisée pour les nouvelles applications

- Soit

INITCOMMONCONTROLSEX iccInit;

//Initialisation et chargement de la barre de status (en autre, mais aussi d'autres barres)
iccInit.dwSize = sizeof ( iccInit );
iccInit.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx ( &iccInit );

qui est donc à préférer à la commande précédente...

Image non trouvée ! InitCommonControls() nécessitera l'ajout de la librairie COMCTL32.LIB dans votre projet (voir à la fin de ce chapitre).

Ensuite, vous pouvez créer un objet Barre de status en utilisant la fonction CreateWindowEx() (remarque, il existait aussi CreateStatusWindow() qui est dépassée maintenant).

hwndStatus = CreateWindowEx(0,

STATUSCLASSNAME,
(LPSTR) NULL,
SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE,
0,
0,
0,
0,
hwnd,
(HMENU) ID_STATUS,
hInst,
NULL);

hwndC1 = CreateWindowEx(0,

STATUSCLASSNAME,
(LPSTR) NULL,
SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE | style de la barre de status ou rien (par ex. SBARS_SIZEGRIP),
0,
0,
0,
0,
hwndParent,
(HMENU) n°ID,
hInstance,
NULL);


Les coordonnées ne seront pas renseignées. La barre de status générant automatiquement ses origines par rapport aux styles passés en paramètre ainsi qu'à la taille de la fenêtre parent.

 

Pour détruire l'objet

Simplement par la fonction CloseWindow (hwndButton); ou DestroyWindow(hwndButton);

 

Lire ou paramétrer le contrôle

On lira ou paramétrera le contrôle via la fonction SendMessage () de la manière suivante:

resultat = SendMessage (Handle de l'objet "Status Bar", message commençant par SB_ ou WM_ (Voir paragraphe Les messages), option dans wParam, option dans lParam);

 

Particularités de ce contrôle

- Si la fenêtre parent vient à changer de taille, il faut informer la barre de status que cette taille a changé (sinon, elle restera bêtement à sa place avec une taille ne correspondant plus à celle de sa fenêtre parent). Il faudra donc traiter le message WM_SIZE dans le parent et ajouter une ligne SendMessage (hwndStatus, WM_SIZE, wParam, lParam); où hwndStatus est le handle de la barre de status.

- Il est possible de subdiviser la barre de status en différent champs de status (maximum 256), chacun de ces champs pouvant alors afficher une ligne particulière. Pour cela, vous utiliserez le message SB_SETPARTS. (Voir le chapitre sur les messages ci-après).

 

Les messages

SB_SETMINHEIGHT: Il est possible de définir la hauteur de la zone d'affichage de la fenêtre de status (Hors bordures donc !). wParam aura pour valeur la hauteur en pixel. lParam sera à 0.

SB_SETPARTS: Permet de subdiviser la barre de status en plusieurs sous zones de status. wParam contenant le nombre de subdivision à faire (pas plus de 256). lParam pointant sur un tableau de type entier dans lequel vous retrouverez les positions des différentes barres permettant les subdivisions (il doit donc y avoir autant de valeurs qu'il y a de subdivisions en principe !).

Image non trouvée !

Il faut bien comprendre que l'on indique via ce message la position des barres de séparations des subdivisions par rapport à une origine qui est toujours le bord à gauche de la fenêtre de status. Il ne s'agit donc pas de la taille des subdivisions ! Pour connaître la taille de la 2ième subdivision dans l'exemple ci-dessus, il faudra faire: position de la barre de subdivision 1 - position de la barre de subdivision 2.

Le tableau qui sera passé sera donc pour notre exemple : {100, 200, 300}

Si vous aviez indiqué -1 pour la 3 ième subdivision, alors le champ aurait occupé le restant de la place disponible de la barre de status.

SB_GETPARTS: Permet de récupérer les positions des barres de droites des différentes subdivisions correspondantes et de connaître le nombre de subdivisions dans la barre de status. wParam contiendra le nombre de subdivisions pour lequels on veut connaître la largeur (Si le nombre est plus grand que le nombre de subdivisions, la fonction se limitera évidemment aux nombres totals de subdivisions). lParam pourra pointer sur un tableau d'entiers qui pourra au moins recevoir la positions de tous les barres de subdivisions indiquées dans wParam ! La valeur de lParam pourra être nulle si le but est uniquement de connaître le nombre de subdivisions car la fonction SendMessage retournera toujours le nombre total de subdivisions.

SB_GETBORDERS: permet de récupérer la largeur des bordure de la status bar. Le message devra inclure l'adresse d'un tableau de 3 éléments qui recevront la largeur.
SB_SETTEXT: ce message permet:

  1. D'afficher un texte dans une subdivision:wParam recevant le numéro de la subdivision dans lequel on veut afficher du texte. lParam est un pointeur sur la chaîne de caratères (Utilisez (LPARAM) adresse du texte)).
  2. D'aligner le texte dans la subdivision:Par défaut, le texte est aligné à gauche. Il est possible de le centrer en mettant \t au début du texte ou de l'aligner à droite en mettant \t\t au début du texte.
  3. Définir le style de la zone de subdivision: On passera le style dans wParam. Je sais, dans wParam vous avez déjà le numéro de la subdivision. Mais cette valeur étant inférieure à 256, toutes valeurs supérieures pourront être utilisées de la manière suivante : wParam = n° subdivision | style où style pourra avoir la ou les valeurs suivantes:
Valeur Styles
0 Le texte apparaît sur une surface qui semble enfoncée par rapport à la surface de la barre status (Valeur par défaut si vous ne précisez pas de style évidemment !)
SBT_NOBORDERS La texte apparaît sur une surface qui est à la même hauteur que la surface de la barre status. cela aura pour effet de ne plus afficher les bordures
SBT_POPOUT Le texte apparaît sur une surface qui semble plus haute par rapport à la surface de la barre status
SBT_OWNERDRAW Le texte sera affiché par la fenêtre parent.
SBT_RTLREADING le texte sera affiché de droite à gauche.

SB_GETTEXTLENGTH: Ce message permet de connaître la taille en caractère de la chaîne de caractères contenu dans une subdivision. ainsi que le style utilisé. wParam contient la valeur de la subdivision pour laquelle on veut ces informations. lParam sera à 0. En sortie, vous obtenez une valeur 32 bits. La partie basse étant le nombre de caractères. La partie haute contenant le ou les styles.

SB_GETTEXT: Permet derécupérer la chaîne de caractères dans une subdivision de la barre de status. On pourra utiliser SB_GETTEXTLENGTH pour connaître la taille de la chaîne avant de la récupérer. wParam = n° de la subdivision de la barre de status. lParam contient un pointeur sur une chaîne de caractères qui recevra le texte. La fonction SendMessage retournera une valeur sur 32 bits identique à SB_GETTEXTLENGTH.

Il est à priori possible d'utiliser WM_SETTEXT, WM_GETTEXT, ou WM_GETTEXTLENGTH sur la barre de status n'est pas subdivisée.

SB_SETTIPTEXT: Permet d'afficher un tooltip pour une subdivision. wParam recevant le n° de la subdivision sur laquelle vous désirez un tooltip. lParam pointant sur une chaîne de caractères qui sera le texte affiché.

Image non trouvée ! Le tooltip ne s'affichera que si le texte ne tient pas dans la zone d'affichage (texte trop grand) ou si vous affichez une icône. De plus, le tooltip ne sera géré que si le style SBT_TOOLTIPS est positionné lors de la création de la barre de status.

SB_GETTIPTEXT: Permet de récupérer le texte d'un tooltip d'une subdivision. wParam devant contenir le n° de subdivision et la taille maximum à récupérer (Il n'y a pas de SB_GETTIPTEXTLENGTH). Pour coder ses informations dans wParam, vous utiliserez la macro MAKEWPARAM (n°subdivision, Taille). lParam contenant l'adresse d'un buffer qui recevra la chaîne de caractères.

Image non trouvée !le tooltip ne sera géré que si le style SBT_TOOLTIPS est positionné lors de la création de la barre de status.

SB_ISSIMPLE: Permet de savoir si l'objet est en mode simple (pas de subdivision). wParam = 0, lParam = 0L. La fonction retourne 0 si des subdivisions existent.

SB_SIMPLE: Permet de passer ou repasser une barre de status en mode simple (pas de subdivision. Voir le message SB_SETPARTS). wParam = TRUE pour mode simple.

SB_SETICON: Permet d'afficher une icône dans une subdivision. wParam contenant la valeur de la subdivision (-1 possible pour le mode simple), lParam contenant le handle de l'icône qui peut être à 0 (dans ce cas, l'icône éventuellement affichée sera effacée).

SB_GETICON: Permet de récupérer le handle d'une icône éventuellement présente dans une subdivision. wParam contient le n° subdivision(-1 possible pour le mode simple). lParam étant à zéro. SendMessage retournera alors le handle ou NULL si problème.

SB_GETRECT: Permet de récupérer les coordonnées sous forme RECT d'une subdivision. wParam contient le n° subdivision. lParam pointe sur une structure RECT qui recevra les coordonnées. La fonction retourne TRUE si ok, FALSE si pb.

SB_SETBKCOLOR: Permet de changer la couleur de fond. wParam à 0, lParam contiendra CLR_DEFAULT (pour utiliser la couleur par défaut) ou la couleur au format COLORREF. (N'oubliez pas la macro RGB pour la conversion). En sortie, la fonction retourne la couleur utilisée précédemment (qui pourra être CLR_DEFAULT).

SB_GETBORDERS: Permet de récupérer l'épaisseur de la barre horizontale, verticale et de la barre entre deux subdivisions. wParam etant à 0 et lParam pointant sur un tableau de 3 éléments de type entier.

 

Le message SB_SETTEXT:

Vous avez vaguement vu le style SBT_OWNERDRAW.

En fait, ce message va permettre d'avoir un peu plus la main sur l'affichage. Vous pouvez passer ce que vous voulez dans lParam (un handle, une valeur, ...) car cette valeur sera récupérée dans la procédure de gestion des messages de la fenêtre parent (voir juste après le champ itemData de la structure de type DRAWITEMSTRUCT). En fait, lorsqu'une subdivision qui a le style SBT_OWNERDRAW a besoin de se redessiner, elle envoye à la fenêtre parent le message WM_DRAWITEM. wParam sera alors l'Id de la fenêtre de status. lParam sera un pointeur sur une structure de type DRAWITEMSTRUCT:

typedef struct tagDRAWITEMSTRUCT {
UINT CtlType;
UINT CtlID;
UINT itemID;
UINT itemAction;
UINT itemState;
HWND hwndItem;
HDC hDC;
RECT rcItem;
ULONG_PTR itemData;
} DRAWITEMSTRUCT;

Les champs utilisables seront:

CtlID qui contient le numéro d'identification de la barre de status. On pourra donc le contrôler.

itemID lui correspond à la subdivision qui a envoyé le message WM_DRAWITEM.

hwndItem qui est le handle de la barre de status (que vous pourrez contrôler)

hDC qui est le contexte de périphérique utilisé

rcItem coordonnées de type RECT par rapport au coin supérieur gauche de la barre de status de la portion à redessiner

et enfin itemData qui est la valeur lParam que vous aviez passé avec le style SBT_OWNERDRAW.

 

Réception de messages sur la fenêtre parent:

La barre de status va envoyer un message WM_NOTIFY dans les cas suivants:

NM_CLICK clique bouton gauche de la souris.

NM_DBLCLK double cliques bouton gauche de la souris.

NM_RCLICK clique bouton droit de la souris.

NM_RDBLCLK double cliques bouton droit de la souris.

SBN_SIMPLEMODECHANGE lorsque la barre de status reçoit un SB_SIMPLE.

Dans wParam, vous obtenez un identificateur qui devrait être celui de la barre de status ou d'un autre objet. Il faudra donc le contrôler. Pour être certain de l'objet, il faut le vérifier soit dans hwndFrom soit dans idFrom.

Dans ce cas, lParam pointe sur une structure NMMOUSE:

typedef struct tagNMMOUSE {
NMHDR hdr;
DWORD_PTR dwItemSpec;
DWORD_PTR dwItemData;
POINT pt;
LPARAM dwHitInfo;
} NMMOUSE, *LPNMMOUSE;

Avec pt qui contient les coordonnées de la souris.

dwItemSpec contiendra le numéro de la subdivision cliquée.

hdr qui pointe sur une structure:

typedef struct tagNMHDR {
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR;

ou hwndFrom est le handle de la barre de status.

idFrom et le numéro ID de la fenêtre barre de status.

code contient le message NM_xxx ou SBN_xxx.

 

Pour gérer le clique dans la barre de status, il faudra donc un code de ce type dans la procédure de gestion des messages de la fenêtre parent:

que l'on pourrait completer par exemple si l'utilisateur clique sur la 2 ième subdivision:

if (nmmouse->dwItemSpec == 1) // Ne pas oublier que l'on commence à 0 !

 

Autres fonctions:

Comme déjà indiqué au début de ce document : DrawStatusText().

Mais aussi: MenuHelp() qui doit permettre de positionner de l'aide. Jamais essayé. Pour plus d'informations, voir chez Microsoft.

 

Un exemple

Vous constaterez que pour faire avancer la barre de progression, j'utilise un timer...Si vous ne connaissez pas, il s'agit dans cet exemple de recevoir tout les 1000 ms (théoriquement) un message WM_TIMER qui permettra de traiter le cas de l'affichage et de l'effacement d'un icône via le message SETTEXT.

Le code Image non trouvée !

Une icôneImage non trouvée !

Fichier ressource sur l'icôneImage non trouvée !

Le fichier .h de la ressourceImage non trouvée !

Sous Visual C++, il faut se créer un projet Win32 et mettre les fichiers dans le répertoire correspondant au projet. Puis inclure les fichiers: code, ressource et ressource.h.(Project\Add to project\Files).

Image non trouvée ! Si vous obtenez une erreur de compilation sur InitCommonControls(), c'est certainement parce que vous n'avez pas la librairie COMCTL32.LIB dans votre projet (C'est le cas par défaut).

Sous Visual C++ le menu Project/settings et dans l'onglet link, ajoutez COMCTL32.LIB

Sous Dev-C++, le menu Project/Project options et dans le champ Further object files or linker options blablabla, ajoutez C:\Dev-C++\Lib\libcomctl32.a via le bouton (Le chemin peut varier suivant votre installation de Dev-C++. Mais dans tous les cas, cette librairie se trouve dans le répertoire Lib de Dev-C++).