Vue d'ensemble de l'architecture Windows de base


Nouveaux concepts :

Types de fenêtres
Messages Windows
La procédure de fenêtre
La classe de fenêtre
La file de messages et la boucle de messages
Boîtes de dialogue et contrôles de fenêtres enfant
Handles (handles)

 


Cette section est nécessaire avant de continuer afin de comprendre les concepts entourant les fenêtres et les boîtes de dialogue.

Types de fenêtres

La programmation Windows est orientée objet, les fenêtres étant les principaux objets. Il existe différents types de fenêtres, tels que la fenêtre principale d'une application, qui peut contenir une barre de titre affichant le nom du programme, un menu, et éventuellement une barre d'outils et une barre de défilement. D'autres types de fenêtres comprennent les boîtes de dialogue, qui peuvent avoir ou non une barre de titre, et les boîtes de message basiques. Les boutons poussoirs, les boutons radio, les cases à cocher, les listes, les barres de défilement, les barres de progression et les champs de saisie de texte qui font partie d'une fenêtre principale sont également des types de fenêtres appelés "contrôles de fenêtres enfant". Nous discuterons des boîtes de dialogue et des contrôles de fenêtres enfant plus en détail ci-dessous.

Une fenêtre standard comporte deux zones importantes. La zone cliente est la partie principale d'une fenêtre où l'application affiche du texte ou des graphiques. La barre de titre, la barre de menu, le menu de la fenêtre, les boutons de réduction et d'agrandissement, la bordure de redimensionnement et les barres de défilement sont collectivement appelés la zone non-cliente de la fenêtre. Le système gère la plupart des aspects de la zone non-cliente, tandis que l'application gère l'apparence et le comportement de sa zone cliente.

1

Messages Windows

Les fenêtres reçoivent les entrées de l'utilisateur, telles que les interactions clavier ou souris, sous la forme de "messages Windows" provenant du système d'exploitation. Une fenêtre utilise également des messages pour communiquer avec d'autres fenêtres. Par exemple, lorsque l'utilisateur redimensionne la fenêtre d'une application en faisant glisser sa bordure, le système d'exploitation gère tout le code complexe permettant de modifier la taille de la fenêtre, mais l'application répond en ajustant son affichage pour remplir la nouvelle fenêtre. Comment l'application sait-elle quand la fenêtre a été redimensionnée ? Le système d'exploitation envoie à la fenêtre du programme un message lui indiquant le changement. Un autre exemple est celui d'une fenêtre de bouton-poussoir qui sait qu'elle a été "cliquée". Dans la plupart des programmes Windows, la majeure partie du programme est consacrée au traitement des messages. Un message se compose d'un identifiant de message (MessageID) commençant par des lettres indiquant le type de message (par exemple WM_) et de deux paramètres (lParam et wParam) qui contiennent des informations supplémentaires si nécessaire.

La procédure de fenêtre

Le système d'exploitation envoie des messages à un programme en appelant une fonction spéciale (la "procédure de fenêtre" ou WndProc) à l'intérieur de celui-ci et en transmettant le message en tant que paramètre. Les fonctions écrites par le programmeur que le système d'exploitation appelle de cette manière sont appelées "procédures de rappel" (callback procedures). Chaque fenêtre créée par un programme a une procédure de fenêtre associée qui traite les messages provenant du système d'exploitation et des autres fenêtres. Toute l'action réelle se produit dans la procédure de fenêtre - presque tout ce qu'un programme Windows fait est en réponse à un message destiné à une procédure de fenêtre. La procédure de fenêtre détermine ce que la fenêtre affiche dans sa zone cliente et comment la fenêtre réagit aux entrées de l'utilisateur. Windows appelle WndProc lorsqu'une fenêtre est créée et détruite. Votre procédure de fenêtre recevra des messages qu'elle n'a pas besoin de traiter elle-même, et dans ce cas, vous devez transmettre le message au gestionnaire de messages par défaut de Windows (DefWindowProc) pour traitement.

La classe de fenêtre

Une fenêtre est toujours créée sur la base d'une "classe de fenêtre". La classe de fenêtre définit la procédure de fenêtre qui traite les messages destinés à la fenêtre. L'utilisation d'une classe de fenêtre permet de créer plusieurs fenêtres basées sur la même classe et donc d'utiliser la même procédure de fenêtre. Par exemple, toutes les fenêtres de boutons - y compris les boutons-poussoirs, les cases à cocher et les boutons radio - sont créées sur la base de la même classe de fenêtre. Cette classe de fenêtre est associée à une procédure de fenêtre située dans une DLL système qui traite les messages de toutes les fenêtres de boutons. Avant de créer une fenêtre d'application, vous devez enregistrer une classe de fenêtre en appelant la fonction RegisterClass. La classe de fenêtre définit également les caractéristiques générales d'une fenêtre, y compris les icônes et la couleur de fond.

Lorsque vous créez une fenêtre en appelant la fonction CreateWindow, vous spécifiez des informations plus détaillées sur l'apparence de la fenêtre. Par exemple, nous savons que tous les boutons-poussoirs fonctionnent de la même manière car ils utilisent tous la même procédure de fenêtre (WndProc), mais tous les boutons-poussoirs ne se ressemblent pas. Ils peuvent avoir des tailles différentes, des emplacements différents à l'écran et des chaînes de texte différentes. Ces caractéristiques font partie de la définition de la fenêtre plutôt que de la classe de fenêtre.

Les contrôles de fenêtre enfants mentionnés ci-dessus ont 6 classes prédéfinies : BUTTON, COMBOBOX, EDIT, LISTBOX, SCROLLBAR et STATIC. Ces "contrôles communs" sont enregistrés en appelant la fonction InitCommonControls.

La file d'attente de messages et la boucle de messages

Lorsqu'un programme Windows démarre son exécution, le système d'exploitation crée une "file d'attente de messages" pour le programme. Cette file d'attente de messages stocke les messages destinés à toutes les fenêtres qu'un programme pourrait créer. Une application Windows comprend une petite portion de code appelée "boucle de messages" qui récupère les messages de la file d'attente en appelant la fonction GetMessage et les envoie à la procédure de fenêtre appropriée en appelant DispatchMessage. D'autres messages sont envoyés directement à la procédure de fenêtre sans être placés dans la file d'attente.

On dit que les messages en file d'attente sont "postés" dans la file d'attente de messages, tandis que les messages non en file d'attente sont "envoyés" à la procédure de fenêtre. Les messages en file d'attente sont généralement le résultat des entrées utilisateur sous forme de frappes de touches, de caractères découlant des frappes de touches, de mouvements de souris et de clics de boutons de souris, mais ils incluent également le message de redessin pour rafraîchir l'affichage (WM_PAINT) et le message de sortie (WM_QUIT). Les messages non en file d'attente regroupent tout le reste et proviennent souvent de l'appel de fonctions Windows. Par exemple, lorsque WinMain appelle CreateWindow, Windows crée la fenêtre et envoie à la procédure de fenêtre un message WM_CREATE dans le processus.

Boîtes de dialogue et contrôles de fenêtre enfants

Les boîtes de dialogue ne sont rien de plus que des fenêtres normales conçues pour fonctionner avec des contrôles de fenêtre enfants. Elles peuvent être utilisées comme dispositif d'entrée pour la fenêtre principale de votre application ou comme fenêtre principale elle-même. La taille et la disposition d'une boîte de dialogue et de ses contrôles sont définies dans un "modèle de boîte de dialogue" dans une ressource de script. Cela peut être écrit manuellement, mais il est préférable de le configurer à l'aide de l'éditeur de ressources visuelles de WinAsm.

Lorsqu'un programme invoque une boîte de dialogue basée sur un modèle, Windows est responsable de la création de la fenêtre contextuelle de la boîte de dialogue et des contrôles de fenêtre enfants, ainsi que de la fourniture d'une procédure de fenêtre pour traiter les messages de la boîte de dialogue, y compris toutes les entrées clavier et souris. Étant donné que les contrôles de fenêtre enfants traitent leurs propres messages de souris et de clavier et notifient la fenêtre parent lorsque leur état change, cela soulage énormément la charge des programmeurs. Le code à l'intérieur de Windows qui gère tout cela est parfois appelé le "gestionnaire de boîte de dialogue".

De nombreux messages traités par le gestionnaire de boîtes de dialogue sont également transmis à une procédure de rappel dans votre propre programme, appelée "procédure de boîte de dialogue" ou "procédure de dialogue". Une procédure de boîte de dialogue est similaire à une procédure de fenêtre, car Windows envoie des messages à la procédure lorsqu'il a des informations à transmettre ou des tâches à exécuter. La plupart des procédures de boîte de dialogue traitent le message WM_INITDIALOG et les éventuels messages WM_COMMAND envoyés par les contrôles, mais traitent rarement, voire jamais, d'autres messages.

Contrairement à une procédure de fenêtre, une procédure de boîte de dialogue n'appelle jamais la fonction DefWindowProc. Au lieu de cela, elle renvoie la valeur TRUE si elle traite un message ou FALSE si ce n'est pas le cas. En d'autres termes, si une procédure de dialogue ne traite pas un message, elle doit renvoyer FALSE pour indiquer à Windows de traiter les messages en interne. La seule exception à cette règle est le message WM_INITDIALOG. La procédure de boîte de dialogue doit renvoyer TRUE pour indiquer à Windows de poursuivre le traitement du message WM_INITDIALOG.

Vous pouvez communiquer avec n'importe quel contrôle de fenêtre enfant dans une boîte de dialogue (via son numéro d'identification de contrôle unique) en utilisant la fonction SendDlgItemMessage. Win32.hlp répertorie les messages disponibles, mais Windows fournit également plusieurs fonctions API spécifiques aux contrôles pour obtenir et définir rapidement des données, par exemple GetDlgItemText, CheckDlgButton, etc. Ces fonctions spécifiques aux contrôles sont fournies pour faciliter la tâche du programmeur et rendre le code source plus lisible. Utilisez SendDlgItemMessage uniquement si aucune autre fonction spécifique au contrôle n'est disponible.

Les 2 principaux types de boîtes de dialogue

Modal - le plus courant, par exemple la boîte "À propos" dans le menu d'aide. L'utilisateur ne peut pas basculer entre la boîte de dialogue et une autre fenêtre de votre programme. L'utilisateur doit d'abord répondre à la boîte de dialogue. Cependant, l'utilisateur peut basculer vers un autre programme. Créée en appelant DialogBoxParam, qui ne renvoie une valeur qu'après la destruction de la boîte de dialogue. Si vous incluez le style DS_SYSMODAL dans le modèle de boîte de dialogue, cela produira une boîte de dialogue modale système qui doit être fermée avant que l'utilisateur puisse faire autre chose dans Windows.

Modeless - par exemple, la boîte de recherche de texte dans un traitement de texte. Permet à l'utilisateur de basculer entre la boîte de dialogue et la fenêtre qui l'a créée, ainsi que d'autres programmes. Créée en appelant CreateDialogParam, qui renvoie immédiatement le Handle de la fenêtre de la boîte de dialogue.

Il existe plusieurs autres différences importantes :

1. Les boîtes de dialogue modeless incluent généralement une barre de légende et une boîte de menu système pour permettre à l'utilisateur de déplacer la boîte de dialogue vers une autre zone de l'affichage à l'aide de la souris ou du clavier. Vous n'avez pas besoin de cela avec une boîte de dialogue modale car l'utilisateur ne peut rien faire dans la fenêtre sous-jacente de toute façon.

2. Si vous n'incluez ni le style WS_VISIBLE ni l'appel à ShowWindow, une boîte de dialogue modeless ne sera pas du tout affichée.

3. Contrairement aux messages destinés aux boîtes de dialogue modales et aux boîtes de message, les messages destinés aux boîtes de dialogue modeless passent par la file d'attente de messages de votre programme, qui doit être modifiée pour transmettre ces messages à la procédure de fenêtre de la boîte de dialogue.

Boîtes de dialogue communes

Windows a préparé des boîtes de dialogue "communes" prédéfinies à utiliser par vos applications, notamment les boîtes de dialogue de fichiers, d'impression, de couleur, de police et de recherche. Elles existent pour fournir une interface utilisateur standardisée et résident dans comdlg32.dll, donc pour les utiliser, vous devez vous lier à comdlg32.lib. Vous créez ces boîtes de dialogue en appelant les fonctions appropriées de la bibliothèque de boîtes de dialogue communes. Pour la boîte de dialogue "Ouvrir un fichier", il s'agit de GetOpenFileName, pour la boîte de dialogue "Enregistrer sous", il s'agit de GetSaveFileName, pour la boîte de dialogue "Imprimer", il s'agit de PrintDlg, et ainsi de suite. Chacune de ces fonctions prend un pointeur vers une structure en tant que paramètre. Elles sont répertoriées dans Win32.hlp.

WinMain, Handles et Instances

Le point d'entrée d'un programme Windows est la fonction WinMain, appelée par le système d'exploitation pour démarrer l'exécution après que le programme a été chargé depuis le disque dans la mémoire par le chargeur Windows. Dans les programmes C/C++, l'étiquette "WinMain" doit être utilisée, mais en assembleur, n'importe quelle étiquette peut être utilisée. Lorsqu'un exécutable est mappé en mémoire par le chargeur Windows, la version en mémoire est appelée module. Dans Windows 32 bits, l'adresse de départ en mémoire (adresse linéaire) à partir de laquelle le mappage de fichier commence correspond à le Handle du module.

Un Handle est simplement un nombre de 32 bits (de la taille d'un DWORD) que le système d'exploitation utilise pour identifier de manière unique chaque objet qu'il crée, comme une fenêtre ou un bouton. Vous obtenez le Handle de Windows, puis utilisez cet Handle dans d'autres fonctions. Le Handle du module identifie le programme. Le Handle du module est également appelée "Handle d'instance", qui est le premier paramètre pris par la fonction WinMain et est requis en tant qu'argument pour les autres fonctions Windows.

Dans les premières versions de Windows, lorsque vous exécutiez plusieurs instances du même programme, toutes les instances de l'application partageaient le code et la mémoire en lecture seule. Un programme pouvait déterminer si des instances précédentes de lui-même étaient en cours d'exécution, puis sauter certaines tâches et déplacer les données de l'instance précédente dans sa propre zone de données. Dans les versions 32 bits de Windows, ce concept a été abandonné. La "Handle de l'instance précédente" est restée le deuxième paramètre de WinMain, mais elle est maintenant toujours NULL ou 0.

Applications GUI faciles à l'aide de boîtes de dialogue

Les boîtes de dialogue peuvent être utilisées comme périphérique d'entrée pour la fenêtre principale de votre application ou pour la fenêtre principale elle-même. Cela est réalisé en appelant DialogBoxParam pour créer une boîte de dialogue modale sans fenêtre parent. Cette approche simplifie considérablement la conception du programme en utilisant une procédure de dialogue au lieu d'une procédure de fenêtre et rend une boucle de messages inutile car les messages sont envoyés directement à la procédure de dialogue. La boîte de dialogue peut être créée à partir d'un script de ressource réalisé dans un éditeur visuel utilisant des contrôles de fenêtre enfants qui effectuent la plupart de leur propre traitement de messages. Vous n'avez même pas besoin d'enregistrer une classe de fenêtre. Nous utiliserons cette approche pour les exemples de ce tutoriel.

 


Copyright (C)- xtx Team (2021)

XHTML valide 1.1 CSS Valide !