Activer/désactiver une option de menu
Concernant les menus item:
Il peut être intéressant de rendre ou non disponible l'accès à certaines options d'un menu.
Par exemple, vous avez une application dans lequel se trouve 1 à n éditeurs. Le menu associé à votre application a les options couper, copier ou encore coller. Il peut être intéressant de désactiver ces 3 options si vous avez clôturé tous les éditeurs de votre application, il semble en effet difficile de pouvoir coller quoi que ce soit ! De même, l'option coller devrait être désactivé s'il n'y a rien à coller dans votre application.
EnableMenuItem:
Pour activer/désactiver une option de menu, nous utiliserons la fonction:
EnableMenuItem (hMenu, n°Id, option)
Avec hMenu qui est le handle du menu principal
n°Id étant la valeur de votre MENUITEM ou une position suivant option..
option qui pourra prendre les valeurs MF_ENABLED pour activer l'élément,
MF_DISABLED pour désactiver, MF_GRAYED pour griser et désactiver
l'option. .
Il est possible aussi d'indiquer comment retrouver l'option du menu, soit par sont identifiant, on passera alors MF_BYCOMMAND soit par sa position (en commençant par 0) dans le menu, on passera alors MF_BYPOSITION. Par défaut, l'option est MF_BYCOMMAND.
Concernant le handle du menu, soit vous l'avez stocké dans une variable globale et a été affecté lors d'un appel à LoadMenu,
soit vous ne le connaissez pas, ou votre procédure de message gère plusieurs instances de fenêtre !
GetMenu():
Dans ce cas, il faut le retrouver. Un menu principal étant associé à une fenêtre, on pourra utiliser une fonction hMenu=GetMenu (hWnd) où hWnd est le handle de la fenêtre (Ce handle étant passé en paramètre à notre procédure de message). Cette fonction retournera alors le handle du menu principal de notre fenêtre.
GetSubMenu():
Il existe aussi une fonction pour récupérer les sous-menus:
HMENU GetSubMenu( hMenu, nPos); qui retourne NULL si l'élément n'est pas un sous-menu.
A quel moment peut-on désactiver/activer une option de menu:
Hormis avant la création d'une fenêtre ou après sa destruction ou encore à la conultation du menu par l'utilisateur, on peut modifier le menu à tout moment.
Cependant, il peut être intéressant d'utiliser le message WM_INITMENUPOPUP qui est reçue à chaque fois que windows dessine un menu à l'écran. Nous pourrons alors modifier l'état actif ou non (mais aussi bien d'autres choses) d'une option de menu avant que l'utilisateur ne le voit.
Rappel:
Si vous désactivez un menu en dehors d'un traitement d'affichage, il faudra utiliser DrawMenuBar (hwnd) pour forcer Windows à redessiner le menu.
Remarque:
Dans le cas d'activation ou de désactivation de plusieurs options du menu causées par certaines conditions, il peut être intéressant de passer par un tableau dans lequel on indiquera tous les Id des MENUITEM à désactiver.
Cas d'utilisation:
Cette fonction sera utilisée pour activer ou désactiver l'option de menu "Coller" par rapport au contenu du presse-papier(ou Clipboard, étudié dans un autre chapitre):
EnableMenuItem (wParam, IDM_PASTE, IsClipboardFormatAvailable (CF_TEXT) ? MF_ENABLED
: MF_GRAYED);
Exemple:
Etat d'un menu:
Dans l'exemple ci-dessus, j'utilise des variables pour connaître l'état des options de menu. Cependant, il peut être préférable d'utiliser une autre méthode:
En autre GetMenuState()
Syntaxe:
UINT GetMenuState(
HMENU hMenu,
UINT uId,
UINT uFlags
);
Les Parametres sont alors:
hMenu: pour le handle de menu
uId: Soit l'identifiant de notre menu, soit un index (commençant à
0) suivant la valeur de uFlags.
uFlags Indique la manière d'utiliser uId:
MF_BYCOMMAND: Dans ce cas, uId est l'identifiant de menu.
MF_BYPOSITION: Index dans le menu en commençant à 0.
Si l'item n'existe pas, la fonction retourne -1.
Si l'élément est un menu popup, la partie basse indique les flags associés à l'élément. La partie haute va indiquer le nombre d'item présent dans ce menu popup.
Si l'élément est un item, alors le résultat est une combinaison des flags
Les flags (que nous avons déjà vus) pouvant être MF_CHECKED, MF_DISABLED, MF_GRAYED, MF_HILITE, MF_MENUBREAK, MF_MENUBARBREAK, MF_OWNERDRAW, MF_POPUP et MF_SEPARATOR.
Pour tester les autres valeurs, il suffira de faire:
pour l'équivalent de MF_ENABLED, utiliser ! (Flag&(MF_DISABLED | MF_GRAYED))
MF_STRING, utiliser ! (Flag&(MF_BITMAP | MF_OWNERDRAW))
MF_UNCHECKED, utiliser ! (Flag&MF_CHECKED)
et MF_UNHILITE, utiliser ! (Flag&HILITE)
où flag et le résultat en sortie de la fonction.
Pas d'exemple, trop simple, mais au cas où, dans le chapitre suivant (marquer ou non une option avec un crochet), j'utiliserai cette fonction dans l'exemple...
Concernant les menus popup:
A ma connaissance, il n'y a pas de solution toute faite.
Par contre, il est possible d'utiliser des fonctions permettant de modifier/manipuler la structure d'un menu. Rien ne nous empêche donc de supprimer un menu popup et de le remplacer par un menu item portant le même nom. Il sera alors possible de modifier son état.
...