Classe GLWindows
Un classe pour gérer OpenGL dans une fenêtre Windows
Je pense que si vous êtes ici, il y a du code que vous connaissez maintenant très bien. Il s'agit de celui qui permet d'intialiser OpenGL dans une fenêtre Windows. Et vous devez sans doute en avoir marre de devoir tout le temps le refaire...
C'est pour cette raison que nous allons regrouper dans une classe (que je nommerai GLWindows) la création d'une fenêtre et l'initialisation d'OpenGL, la gestion des évènements Windows, ainsi que la gestion d'une caméra suivant vos déplacements. Pas de panique, voici les explications...
Il s'agit d'une classe, il y aura donc un constructeur et un destructeur.
Constructeur/destructeur
Le constructeur va mémoriser l'identifiant de notre instance GLWindows (les explications plus tard, lors de la gestion des messages) et créer une classe de fenêtre GLWindows unique à l'instance. La raison de cette unicité est simplement liée à une gestion plus simple de la destruction de la classe de fenêtre Windows. En effet, dès que notre instance de GLWindows sera à détruire, on pourra aussi détruire l'instance de la fenêtre (normal) mais surtout la classe car aucune autre fenêtre n'utilisera plus celle-ci.
Le destructeur va lancer une méthode onDestroyGLW que je laisse virtuelle afin de pourvoir la personnaliser (Voir Polymorphisme/Fonctions virtuelles et classes abstraites et Fonction virtuelle pour classe dérivée). Puis la destroyWindowGLW() (méthode en protected) pour libérer les ressources utilisées par cette classe et destruction de la classe de notre fenêtre windows qui, comme expliqué précédemment, ne servira plus.
Initialisation fenêtre et OpenGL
Notre classe aura besoin de créer une instance de fenêtre Windows de la classe de fenêtre que nous avons défini préalablement dans notre constructeur. A cette instance de fenêtre, nous allons y associer une instance OpenGL. Cette fenêtre pourra occuper la totalité de l'écran (fullscreen) ou non. Dans une résolution que l'on pourra préciser. Pour arriver à celà, j'ai créé la méthode suivante:
openWindowGLW(char* title, int x, int y, int width, int height, int bits, bool fullscreenflag) dans glWindows.cpp
Cette méthode attend en entrée:
char *title qui est le titre de la windows
int x,y qui sont les coordonnées de la windows sachant que ce paramètre ne sert à rien si le mode fullscreen est positionné.
Les valeurs pouvant être -1 ou CW_DEFAULT pour indiquer à Windows qu'il peut positionner la fenêtre où il veut.
int width et height qui sont respectivement la largeur et la hauteur de la zone cliente. J'ai bien dit client et nom de la fenêtre, donc sans les bordures, ... La fenêtre occupera donc une taille plus importante.
int bits : Nombre de bits à utiliser pour la couleur.
fullscreenflag : Vrai pour essayer de passer en mode plein écran, à faux pour le mode fenêtré.
En sortie:
vrai si tout est ok, sinon problème lors de la création et toutes les ressources initialisées durant ce traitement seront refermées.
Cette méthode met en oeuvre pas mal de choses, et déclenchera donc à son tour d'autres méthodes
Voici les explications un peu plus détaillées:
La méthode createWinExGLW(char* title, int x, int y, int width, int height, int bits, bool fullscreenflag), qui reprendra les mêmes paramètres, ce n'est que la création d'une fenêtre Windows en fullscreen ou non. Voici des références aux différents chapitres pour parvenir à cela
- OpenGL en fullscreen ou mode fenêtré - Changer de mode graphique/résolution - Création d'une fenêtre en plein écran ou non - Procédure de gestion des messages Windows - Rappel sur les procédures de messages Windows - Associer une procédure de gestion des messages à notre classe - Des évènements
La méthode initOpenGLGLW(int bits) est ensuite appelée pour initialiser OpenGL sur la fenêtre précédemment créée. Là encore, rien de bien transcendant, voir chapitre:
- Initialiser/détruire une instance OpenGL.
La méthode termine son travail en affichant la fenêtre à l'écran et en lui donnant le focus...
Boucle de traitement
Il s'agit ici d'effectuer tous les traitements liés à notre instance.
trtMsgGLW (bool bBcl);
bBcl est un booleen qui recevra true pour indiquer que l'on entre dans cette méthode et que nous n'avons rien de spécial à faire. Celle-ci ne rendra donc la main que lorsque l'instance sera détruite.
à false, si vous avez besoin de faire des choses. Dans ce cas, la méthode regardera si il y a des choses à faire sur notre fenêtre, si oui, les fait, puis rend la main.
La méthode retournera true pour indiquer que l'instance est maintenant détruite. false sinon.
Donc si vous avez positionné bBcl à false, ce sera à vous de faire en sorte de revenir dans cette méthode tant que celle-ci n'indique pas la fin de l'instance de notre fenêtre pour continuer de gérer la fenêtre et son contenu.
La fonction de cette procédure est en fait très basique, puisqu'il s'agit de vérifier qu''il y a ou non un message dans la file des messages pour notre fenêtre Windows. Si c'est le cas, alors traitement du message. Ce qui va déclencher notre procédure des messages
Cette procédure des messages va à son tour traiter les messages et déclencher des évènements dans notre instance glWindows.
- Voir la liste des évènements
A chaque évènement, il y a un code par défaut. Ces évènements étant virtuels, il sera possible de les redéfinir dans vos classes dérivées (Voir Polymorphisme/Fonctions virtuelles et classes abstraites et Fonction virtuelle pour les classes dérivées).
Ces évènements reçoivent les informations que l'on a par défaut dans une procédure de messages.
Soit pour un message bien spécifique (par exemple onSizeGLW: long type, int width, int height)
Soit pour un regroupement de messages (par exemple onClickMouseGLW qui reçoit le message de la procédure afin de déterminer s'il s'agit d'un simple clic, d'un double clic, ... ou encore onEventGLW(UINT, WPARAM, LPARAM, long&) qui permet de traiter tous les messages que je ne gère pas moi même).
Classe GLWindows
Voici le code !
Je reviendrai plus en détail sur certains points de cette classe par la suite...