Procédure de gestion des messages Windows

 

Tout d'abord un rappel

Les explications sur une procédure de gestion des messages Windows.

 

Un minimum d'explications

Volontairement, j'utilise le C Microsoft plus portable que les classes Microsoft entre les différents compilateurs C, d'où certains problèmes pour faire fonctionner des fonctions natives du C en C++. C'est le cas typiquement de la procédure de gestion des messages.

La lecture des messages commence par la méthode trtMsgGLW qui reçoit un booléen. A vrai, cela indique à la méthode qu'elle ne rend la main qu'à la mort de notre instance. A faux, elle rend systématiquement la main après traitement de la file de messages.

Ce n'est pas cette méthode qui traite directement la file des messages, mais readMsgTrtGLW. readMsgTrtGLW qui lancera la méthode onIdleGLW si aucun message n'est à traiter. Vous pourrez donc surcharger cette méthode pour effectuer des traitements. Par défaut, elle force l'affichage (lancement de la méthode onPaintGLW). Si des messages sont présents, alors il faut retirer le message de la file des messages et lancer la procédure de gestion des messages liée à notre fenêtre Windows pour traiter ce message.

En effet, il y a une procédure de gestion des messages Windows nommée WndProcGLW associée à la fenêtre Windows créée. Cette procédure est définie dans la classe GLWindows afin de permettre le lancement de méthodes privées à la classe. Hors cette procédure est dans le même temps déclarée comme statique (impossible de faire autrement !). Elle ne pourra donc pas lancer dans les instances directement les méthodes correspondantes (tout ce qui est statique est lancé depuis la classe, donc aucune instance n'est connue). Il faut donc une solution pour que la procédure puisse récupérer l'instance de la classe GLWindows correspondant à la fenêtre Windows pour laquelle un message est à traiter.

Image non trouvée !Evidemment, cette procédure est protected, car il n'y a aucune raison d'intervenir dedans !

 

Pour s'en sortir

Lors de l'appel à notre constructeur GLWindows, je mémorise l'instance dans une variable:

lInstance = reinterpret_cast <long> ( this );

Puis, l'instance de GLWindows est passée à la procédure de message de l'instance de la fenêtre lors de la création de notre fenêtre càd via CreateWindowEx() dans le paramètre qui sera récupéré dans lParam de WM_CREATE.

La procédure de messages recevant WM_CREATE mémorisera ensuite définitivement dans la fenêtre via GWL_USERDATA l'instance de notre classe GLWindow (il n'était pas possible de le faire avant, puisque la fenêtre n'existait pas). Cette instance sera ainsi connue lorsque la procédure de messages recevra d'autres messages de la fenêtre, simplement en relisant l'instance directement dans GWL_USERDATA de cette fenêtre. Il sera donc possible de lancer les méthodes GLWindows associées aux messages de la fenêtre en cours de traitement.

hInstGL = GetWindowLong (hWnd, GWL_USERDATA); // Récupération de la valeur
hGLWindow = reinterpret_cast <GLWindows*> ( hInstGL ); // Reconvertir en instance.

 

Des évènements

La procédure de messages va interpréter un bon nombre de messages. Certains ne seront pas renvoyés aux développeurs, ils sont traités automatiquement (par ex. le blocage de la mise en veille, le alt-tab, ...). Mais d'autres donneront lieu à un déclenchement de méthodes dans notre classe (que j'appellerais évènement). Ces méthodes seront là aussi virtuelles afin de permettre de les personnaliser (Voir Polymorphisme/Fonctions virtuelles et classes abstraites et Fonction virtuelle pour les classes dérivées).

Voici la liste, mais elle sera revue plus tard...

Ensuite, suivant votre paramétrage, la méthode onIdleGLW sera lancée afin d'exécuter du code. Cette méthode ne doit bien évidemment pas boucler, sinon, les messages suivant ne seront plus traités ! Par défaut, cette méthode lance la méthode onPaint pour forcer l'affichage.

 

Image non trouvée !Lorsque la procédure de gestion des messages est lancée, elle repositionne systématiquement OpenGL sur le device context ou render context via:

if (hGLWindow->getRCGLW() && hGLWindow->getDCGLW())

wglMakeCurrent(hGLWindow->getDCGLW(), hGLWindow->getRCGLW());