Explication détaillée de la fonction de rappel
Généralités
Bon, voila notre fonction de rappel. Le premier paramètre de notre fonction correspond à l'handle de la fenêtre à qui est adressé le message, le second un identifiant spécifiant le type de message (par exemple, WM_PAINT) et les deux derniers des informations complémentaires à propos de ce message (par exemple les coordonnées de la curseur, si le message est un click de souris..).
Notre fonction va donc déterminer quel type de message lui a été envoyé. Ou plus précisément, elle va essayer de le déterminer si cela l'intéresse. En effet, beaucoup de messages ici ne nous intéressent pas. En effet, on veut juste afficher un peu de texte dans notre fenêtre, on n'a donc pas besoin de gérer la souris, ou le clavier. On va donc intercepter les messages qui nous intéressent, et envoyer les autres à une autre fonction, qui va leur appliquer une gestion par défaut: DefWindowProc, à qui on renvoie les paramètres que l'on reçu.
On fait donc un switch sur le message afin de déterminer son type, et on va particulièrement s'intéresser à deux cas: WM_DESTROY et WM_PAINT. On va commencer par le plus simple: le message WM_DESTROY. Il correspond au moment ou la fenêtre est détruite, pratiquement on va dire le moment ou l'utilisateur a clické sur la petite croix pour fermer la fenêtre :). On va donc envoyer un message WM_QUIT à notre application pour lui dire "C'est terminé, on arrête la boucle de messages et on rend la main à Windows". Pour cela, on emploie la fonction PostQuitMessage, qui prend comme argument un code de sortie, c'est à dire pour dire à l'OS si on quitte le programme de façon normal ou non. Or là, tout se passe bien, on renvoie donc 0.
On fait ensuite un break, afin de sortir du switch et de renvoyer 0 à la fonction de rappel: on a géré le message WM_DESTROY, on ne veut pas lui appliquer une gestion par défaut en le renvoyant à DefWindowProc.
Le message WM_PAINT
Bon, donc comme expliqué auparavant, le message WM_PAINT doit être capable à tout moment de redessiner complètement la fenêtre. Ca tombe bien, nous on n'a pas grand chose à redessiner: on doit juste écrire du texte au milieu de notre fenêtre.
Pour cela on va d'abord récupérer un contexte de périphérique, grâce à la fonction begin paint, qui prend comme premier argument le handle de la fenêtre dans laquelle on veut dessiner, et comme second argument une structure de type PAINTSTRUCT, que l'on n'utilisera pas ici, je ne la détaillerai donc pas plus.
La fonction suivante, GetClientRect, permet de placer dans une structure RECT (elle est pas très compliquée celle la par contre, c'est une structure qui contient 4 entiers long: des coordonnées définissant un rectangle; le premier défini l'abscisse du coté gauche de ce rectangle, le second l'ordonnée du dessus du rectangle, le troisième l'abscisse du coté droit du rectangle, et le quatrième l'ordonnée du coté droit du rectangle). Bref, GetClientRect va stocker dans la structure rect les coordonnées de la zone cliente de notre fenêtre, c'est à dire ce que contient notre fenêtre, barre de titre et bordures exceptées.
Notre fonction DrawText va, comme vous pouvez vous en douter, écrire notre texte dans noter fenêtre. Le premier paramètre est un handle sur le contexte de périphérique récpérer dans notre cas par la fonction BeginPaint, le second le message à afficher. Le troisième paramètre représente la longueur du texte à afficher, en l'occurence, -1 signifie afficher tous les caractères jusqu'à ce qu'on rencontre le caractère NULL (\0).
Le quatrième paramètre représente le rectangle dans lequel on va écrire, dans notre cas le rectangle récupéré par GetClientRect, c'est à dire la zone cliente de notre fenêtre. Enfin, le dernier paramètre recoit une combinaison de flags définissant comment on veut afficher le texte: DT_SINGLELINE signifie qu'on veut afficher le texte sur une seule ligne, DT_CENTER veut dire que le texte doit être horizontalement centré, DT_VCENTER signifie que le texte doit être centré verticalement.
On a maintenant fini de dessiner, donc on appelle la fonction EndPaint (qui prend les mêmes arguments que BeginPaint, et on sort de notre switch pour dire qu'on a fini de traiter le message.