XII. Création du menu : affichage et choix dans le menu▲
Le résultat du premier test de l'écran n'était pas impressionnant mais nous a permis de valider le fonctionnement de l'interface d'écran clScreen
Il faut maintenant lui ajouter de l'affichage et répondre aux commandes de l'utilisateur pour faire un choix dans le menu.
Le code qui suit s'écrit dans le module clScreenMenu.
XII-A. Minuterie▲
N'oublions pas de mettre en place la minuterie !
Dans la procédure ClScreen_ScreenWait, ajoutez l'appel à la méthode Wait de l'objet clGdiplus.
Pour un menu, 10 images par seconde suffisent.
Cette méthode Wait n'est pas bloquante. DoEvents est déclenché dès que nécessaire pour traiter la file de message de l'application et permettre à l'utilisateur d'interagir.
'------------------------------------------------------------------------
' Minuterie d'attente
'------------------------------------------------------------------------
Private
Function
ClScreen_ScreenWait
(
) As
Boolean
' Attente de 1000 / 10 = 100 ms pour affichage de 10 images/s
oGdi.Wait
100
End
Function
Maintenant nous pouvons tester en affichant le UserForm FormGame.
Il ne s'affiche qu'un UserForm vide.
XII-B. Affichage du menu▲
Pour pouvoir dessiner, il faut créer avec gdi+ une image en mémoire.
La création de l'image se fait avec la fonction CreateBitmapForControl de l'objet clGdiplus de l'écran.
L'image créée est de la même taille (en pixels) que le contrôle image Img que nous avions créé sur le formulaire FormGame.
Nous créons cette image à l'initialisation de l'écran de menu dans l'événement Initialize.
With
oGdi
' Nouveau bitmap pour dessiner
.CreateBitmapForControl
FormGame
End
With
Ensuite il faut créer le contenu statique du menu, c'est-à-dire le fond (uni) et le texte des options.
Ce contenu est dessiné une seule fois à l'initialisation de l'écran, puis sauvegardé pour pouvoir être restauré à la demande.
En effet la mise à jour de l'écran dans la fonction UpdateScreen devra :
- recharger le contenu statique du menu ;
- dessiner le contenu dynamique du menu : encadrement de l'entrée sélectionnée, autres animations si nécessaire…
Dans l'événement Initialize nous allons :
- Remplir le fond de gris avec la fonction Clear.
- Écrire le nom du jeu en haut de l'image avec la fonction DrawText.
- Écrire texte de chacune des options avec la fonction DrawText.
Commençons par les deux premières étapes.
' Dessin du contenu statique
With
oGdi
' Nouveau bitmap pour dessiner
.CreateBitmapForControl
FormGame
' Rempli l'image de gris
.Clear
RGB
(
150
, 150
, 150
)
' Ecrit le nom du jeu en haut
.DrawText
"PacMan en VBA"
, 35
, "Arial"
, 0
, 10
, _
.ImageWidth
, 10
+
50
, 1
, 0
, vbBlue
, , vbYellow
End
With
Le code ci dessus rempli l'image de noir puis affiche le texte « Pacman en VBA » en haut et en bleu sur fond jaune.
Pour tester l'affichage, il faut gérer la fonction ClScreen_DisplayScreen.
Utilisons la fonction Repaint de clGdiplus pour dessiner l'image dans le contrôle du formulaire.
'------------------------------------------------------------------------
' Affichage de l'écran
'------------------------------------------------------------------------
Private
Function
ClScreen_DisplayScreen
(
) As
Boolean
' Dessine l'image sur le formulaire
oGdi.Repaint
FormGame.Img
End
Function
Affichez le formulaire avec F5 ou dans le menu Exécution => Exécuter Sub/Userform.
On obtient notre première image.
Ajoutons l'affichage des options :
Pour éviter d'écrire plusieurs fois le même code, on crée une petite procédure d'affichage d'une option.
En paramètre de cette procédure : le numéro de l'option et son texte.
'------------------------------------------------------------------------
' Affichage de l'option numéro pNum avec le texte pText
'------------------------------------------------------------------------
Private
Sub
DisplayOption
(
pNum As
Long
, pText As
String
)
' Position verticale de la première option
Const
cPos As
Long
=
140
With
oGdi
' Dessine un rectangle de fond en jaune pâle
.DrawRectangle
150
, cPos +
(
pNum -
1
) *
60
, 600
, cPos +
(
pNum -
1
) *
60
+
50
, _
RGB
(
255
, 255
, 200
), , , , , "menu"
&
pNum
' Dessine le texte de l'option en bleu
.DrawText
pText, 50
, "Arial"
, 150
, cPos +
(
pNum -
1
) *
60
, _
600
, cPos +
(
pNum -
1
) *
60
+
50
, , , vbBlue
End
With
End
Sub
Le dessin d'une option se fait en deux étapes :
- Dessin d'un rectangle de fond.
- Dessin du texte.
Il faut ajuster les paramètres de position en pixels pour centrer les options.
On pense également à ajouter une région correspondant au rectangle et ayant pour identifiant « menu1 », « menu2 »…
La fonction DrawRectangle permet d'ajout cette région (paramètre pRegion).
Cette région nous servira ensuite à déterminer la région survolée par la souris.
On appelle ensuite cette fonction dans Class_Initialize pour chaque option.
A la fin du dessin du contenu statique, on le sauvegarde en mémoire comme prévu (pour pouvoir restaurer le contenu statique dans la fonction ClScreen_UpdateScreen).
[...
]
' Affichage des options
DisplayOption 1
, "Commencer le jeu"
DisplayOption 2
, "Options"
DisplayOption 3
, "Scores"
DisplayOption 4
, "Crédits"
DisplayOption 5
, "Quitter"
' Sauvegarde l'image en mémoire
.ImageKeep
End
With
Affichez le formulaire pour voir le résultat.
XII-C. Encadrement de l'entrée de menu sélectionnée▲
Pour l'instant on n'a pas encore travaillé sur la gestion des commandes.
On ne connait pas les touches définies par l'utilisateur, nous le verrons lors de la création de l'écran des options.
Nous allons dans un premier temps gérer les choix d'option de menu à la souris.
Lors du survol ou du click sur l'image, un événement est envoyé au contrôle du formulaire.
Pour récupérer cet événement, il nous faut dans notre module clScreenMenu un objet image qui recevra les événéments.
On déclare donc une variable de type Image, avec le mot-clé WithEvents qui permet de recevoir les événéments.
' Contrôle image pour événements
Private
WithEvents oImg As
MSForms.image
Il faut également initialiser l'objet à la création de l'écran.
[...
]
Private
Sub
Class_Initialize
(
)
' Affectation de l'image pour événements
Set
oImg =
FormGame.Img
[...
]
Pour générer le code événément correspondant à un survol de l'image, sélectionnez dans la liste déroulante en haut à gauche l'objet oImg puis dans la liste déroulante à droite sélectionnez MouseMove.
Lors du survol de l'image, la procédure oImg_MouseMove sera exécutée.
Dans cette procédure, nous allons lire (avec RegionGetXY) la région située sous la souris, puis l'affecter à une variable.
Nous pourrons ensuite encadrer cette région dans la fonction ClScreen_UpdateScreen.
On commence par déclarer la variable en en-tête de module :
' Nom de l'option sélectionnée
Private
gOption As
String
Et ensuite on modifie cette variable au survol de la souris.
'------------------------------------------------------------------------
' Sur déplacement de la souris
'------------------------------------------------------------------------
Private
Sub
oImg_MouseMove
(
ByVal
Button As
Integer
, ByVal
Shift As
Integer
, ByVal
X As
Single
, ByVal
Y As
Single
)
Dim
lRegion As
String
With
oGdi
' Région aux coordonnées X et Y
' Les valeurs de X et Y étant des coordonnées prises sur le contrôle,
' on passe ce contrôle en cinquième paramètre
lRegion =
.RegionGetXY
(
X, Y, , , oImg)
If
lRegion <>
""
Then
gOption =
lRegion
End
If
End
With
End
Sub
Et enfin dans la fonction ClScreen_UpdateScreen, on restaure le contenu statique et on encadre l'option sélectionnée.
'------------------------------------------------------------------------
' Mise à jour de l'écran
'------------------------------------------------------------------------
Private
Function
ClScreen_UpdateScreen
(
) As
Boolean
With
oGdi
' Recharge l'image de la mémoire
.ImageReset
' Encadre en rouge l'entrée de menu sélectionnée
.RegionFrame
gOption, vbRed
, 4
End
With
End
Function
Si on affiche le formulaire, l'option de menu survolée s'encadre en rouge.
Mais on a oublié de sélectionner une option par défaut à l'initialisation de l'écran.
'------------------------------------------------------------------------
' Initialisation de l'écran
'------------------------------------------------------------------------
Private
Sub
Class_Initialize
(
)
' Option sélectionnée par défaut
gOption =
"menu1"
[...
]
Deux petits soucis à ce stade de la programmation du menu :
- Si on clique sur le formulaire, l'image ne change plus ensuite.
- L'affichage « clignote » et ça fait mal aux yeux.
Pour le premier problème, on peut forcer le formulaire à se redessiner avec un appel à la méthode Repaint du formulaire.
Pour le second problème, on peut augmenter le paramètre DrawBuffer du formulaire jusqu'à ce que les clignotements disparaissent (valeur maxi = 1048576).
Sinon une autre solution plus simple qui règle les deux problèmes : utilisez la méthode RepaintNoFormRepaint.
Cette méthode dessine l'image directement sur l'écran et évite ainsi tout problème d'affichage.
'------------------------------------------------------------------------
' Affichage de l'écran
'------------------------------------------------------------------------
Private
Function
ClScreen_DisplayScreen
(
) As
Boolean
' Dessine l'image sur le formulaire
oGdi.RepaintNoFormRepaint
FormGame.Img
End
Function
XII-D. Sélection d'une option de menu▲
Toujours à la souris, on va choisir l'option de menu désirée en cliquant sur l'image.
Créez le code événementiel sur souris appuyée MouseDown.
'------------------------------------------------------------------------
' Sur click de la souris
'------------------------------------------------------------------------
Private
Sub
oImg_MouseDown
(
ByVal
Button As
Integer
, ByVal
Shift As
Integer
, ByVal
X As
Single
, ByVal
Y As
Single
)
Call
MenuSelect
End
Sub
On garde en tête qu'on souhaitera plus tard gérer le choix des options au clavier, donc on appelle une fonction MenuSelect qui pourra ensuite servir au clavier.
En fonction du contenu de gOption, on défini le nom de l'écran suivant et on demande le changement d'écran en donnant la valeur Vrai à gChangeScreen.
'------------------------------------------------------------------------
' Sélection dans le menu
'------------------------------------------------------------------------
Private
Sub
MenuSelect
(
)
Select
Case
gOption
Case
"menu1"
gNextScreen =
"game"
gChangeScreen =
True
Case
"menu2"
gNextScreen =
"options"
gChangeScreen =
True
Case
"menu3"
gNextScreen =
"scores"
gChangeScreen =
True
Case
"menu4"
gNextScreen =
"credits"
gChangeScreen =
True
Case
"menu5"
gNextScreen =
"quit"
gChangeScreen =
True
End
Select
End
Sub
Si vous testez le click sur une option de menu, le formulaire se ferme quelque soit l'option choisie.
C'est normal car nous allons ensuite gérer l'enchaînement des écrans dans GameChangeScreen du module clGame au fur et à mesure de leur création.