À propos des classes de fenêtres
Chaque classe de fenêtre a une procédure de fenêtre associée partagée par toutes les fenêtres de la même classe. La procédure de fenêtre traite les messages pour toutes les fenêtres de cette classe et contrôle donc leur comportement et leur apparence. Pour plus d’informations, consultez Window Procedures.
Un processus doit inscrire une classe de fenêtre avant de pouvoir créer une fenêtre de cette classe. L’inscription d’une classe de fenêtre associe une procédure de fenêtre, des styles de classe et d’autres attributs de classe à un nom de classe. Lorsqu’un processus spécifie un nom de classe dans la fonction CreateWindow ou CreateWindowEx , le système crée une fenêtre avec la procédure de fenêtre, les styles et les autres attributs associés à ce nom de classe.
Cette section traite des rubriques suivantes.
- Types de classes de fenêtre
- Comment le système localise une classe Window
- Inscription d’une classe Window
- Éléments d’une classe Window
Types de classes de fenêtre
Il existe trois types de classes de fenêtre :
Ces types diffèrent en termes de portée et de date et de façon dont ils sont enregistrés et détruits.
Classes système
Une classe système est une classe de fenêtre inscrite par le système. De nombreuses classes système sont disponibles pour tous les processus à utiliser, tandis que d’autres sont utilisées uniquement en interne par le système. Étant donné que le système inscrit ces classes, un processus ne peut pas les détruire.
Le système inscrit les classes système pour un processus la première fois que l’un de ses threads appelle une fonction User ou une fonction GDI (Windows Graphics Device Interface).
Chaque application reçoit sa propre copie des classes système. Toutes les applications Windows 16 bits dans le même VDM partagent des classes système, comme elles le font sur Windows 16 bits.
Le tableau suivant décrit les classes système qui peuvent être utilisées par tous les processus.
Classe | Description |
---|---|
Bouton | Classe d’un bouton. |
ComboBox | Classe d’une zone de liste déroulante. |
Modifier | Classe d’un contrôle d’édition. |
ListBox | Classe d’une zone de liste. |
MDIClient | Classe d’une fenêtre cliente MDI. |
ScrollBar | Classe d’une barre de défilement. |
statique | Classe d’un contrôle statique. |
Le tableau suivant décrit les classes système qui sont disponibles uniquement pour une utilisation par le système. Ils sont répertoriés ici pour des raisons d’exhaustivité.
Classe | Description |
---|---|
ComboLBox | Classe de la zone de liste contenue dans une zone de liste modifiable. |
DDEMLEvent | Classe pour les événements DDEML (Dynamic Data Exchange Management Library). |
Message | Classe d’une fenêtre de message uniquement. |
#32768 | Classe d’un menu. |
#32769 | Classe de la fenêtre de bureau. |
#32770 | Classe d’une boîte de dialogue. |
#32771 | Classe de la fenêtre de commutateur de tâches. |
#32772 | Classe pour les titres d’icône. |
Classes globales d’application
Une classe globale d’application est une classe de fenêtre inscrite par un exécutable ou une DLL qui est disponible pour tous les autres modules du processus. Par exemple, votre .dll peut appeler la fonction RegisterClassEx pour inscrire une classe de fenêtre qui définit un contrôle personnalisé en tant que classe globale d’application afin qu’un processus qui charge le .dll puisse créer des instances du contrôle personnalisé.
Pour créer une classe qui peut être utilisée dans chaque processus, créez la classe window dans un .dll et chargez la .dll dans chaque processus. Pour charger le .dll dans chaque processus, ajoutez son nom à la valeur AppInit_DLLs dans la clé de Registre suivante :
HKEY_LOCAL_MACHINE\Logiciel\Microsoft\Windows NT\Currentversion\Windows
Chaque fois qu’un processus démarre, le système charge le .dll spécifié dans le contexte du processus nouvellement démarré avant d’appeler sa fonction de point d’entrée. Le .dll doit inscrire la classe pendant sa procédure d’initialisation et doit spécifier le style CS_GLOBALCLASS . Pour plus d’informations, consultez Styles de classe.
Pour supprimer une classe globale d’application et libérer le stockage qui lui est associé, utilisez la fonction UnregisterClass .
Classes locales d’application
Une classe locale d’application est toute classe de fenêtre qu’un exécutable ou un .dll inscrit pour son utilisation exclusive. Bien que vous puissiez inscrire n’importe quel nombre de classes locales, il est courant d’en inscrire une seule. Cette classe de fenêtre prend en charge la procédure de fenêtre de la fenêtre main de l’application.
Le système détruit une classe locale lorsque le module qui l’a inscrite se ferme. Une application peut également utiliser la fonction UnregisterClass pour supprimer une classe locale et libérer le stockage qui lui est associé.
Comment le système localise une classe Window
Le système gère une liste de structures pour chacun des trois types de classes de fenêtre. Lorsqu’une application appelle la fonction CreateWindow ou CreateWindowEx pour créer une fenêtre avec une classe spécifiée, le système utilise la procédure suivante pour localiser la classe.
- Recherchez dans la liste des classes locales d’application une classe portant le nom spécifié dont le handle instance correspond au handle instance du module. (Plusieurs modules peuvent utiliser le même nom pour inscrire des classes locales dans le même processus.)
- Si le nom ne figure pas dans la liste des classes locales de l’application, recherchez la liste des classes globales d’application.
- Si le nom ne figure pas dans la liste des classes globales de l’application, recherchez la liste des classes système.
Toutes les fenêtres créées par l’application utilisent cette procédure, y compris les fenêtres créées par le système pour le compte de l’application, telles que les boîtes de dialogue. Il est possible de remplacer les classes système sans affecter d’autres applications. Autrement dit, une application peut inscrire une classe locale d’application portant le même nom qu’une classe système. Cela remplace la classe système dans le contexte de l’application, mais n’empêche pas d’autres applications d’utiliser la classe système.
Inscription d’une classe Window
Une classe de fenêtre définit les attributs d’une fenêtre, tels que son style, son icône, son curseur, son menu et sa procédure de fenêtre. La première étape de l’inscription d’une classe de fenêtre consiste à remplir une structure WNDCLASSEX avec les informations de classe de fenêtre. Pour plus d’informations, consultez Éléments d’une classe Window. Ensuite, transmettez la structure à la fonction RegisterClassEx . Pour plus d’informations, consultez Utilisation de classes de fenêtre.
Pour inscrire une classe globale d’application, spécifiez le style CS_GLOBALCLASS dans le membre de style de la structure WNDCLASSEX . Lors de l’inscription d’une classe locale d’application, ne spécifiez pas le style CS_GLOBALCLASS .
Si vous inscrivez la classe window à l’aide de la version ANSI de RegisterClassEx, RegisterClassExA, l’application demande au système de transmettre les paramètres de texte des messages aux fenêtres de la classe créée à l’aide du jeu de caractères ANSI ; si vous inscrivez la classe à l’aide de la version Unicode de RegisterClassEx, RegisterClassExW, l’application demande au système de transmettre les paramètres de texte des messages aux fenêtres de la classe créée à l’aide du jeu de caractères Unicode. La fonction IsWindowUnicode permet aux applications d’interroger la nature de chaque fenêtre. Pour plus d’informations sur les fonctions ANSI et Unicode, consultez Conventions pour les prototypes de fonction.
L’exécutable ou la DLL qui a inscrit la classe est le propriétaire de la classe . Le système détermine la propriété de la classe à partir du membre hInstance de la structure WNDCLASSEX passée à la fonction RegisterClassEx lorsque la classe est inscrite. Pour les DLL, le membre hInstance doit être le handle du .dll instance.
La classe n’est pas détruite lorsque le .dll qui la possède est déchargé. Par conséquent, si le système appelle la procédure de fenêtre pour une fenêtre de cette classe, cela entraîne une violation d’accès, car le .dll contenant la procédure de fenêtre n’est plus en mémoire. Le processus doit détruire toutes les fenêtres à l’aide de la classe avant que le .dll ne soit déchargé et appeler la fonction UnregisterClass .
Éléments d’une classe Window
Les éléments d’une classe de fenêtre définissent le comportement par défaut des fenêtres appartenant à la classe . L’application qui inscrit une classe de fenêtre affecte des éléments à la classe en définissant les membres appropriés dans une structure WNDCLASSEX et en transmettant la structure à la fonction RegisterClassEx . Les fonctions GetClassInfoEx et GetClassLong récupèrent des informations sur une classe de fenêtre donnée. La fonction SetClassLong modifie les éléments d’une classe locale ou globale déjà inscrite par l’application.
Bien qu’une classe de fenêtre complète se compose de nombreux éléments, le système exige uniquement qu’une application fournisse un nom de classe, l’adresse de la procédure de fenêtre et un handle de instance. Utilisez les autres éléments pour définir des attributs par défaut pour les fenêtres de la classe, tels que la forme du curseur et le contenu du menu de la fenêtre. Vous devez initialiser tous les membres inutilisés de la structure WNDCLASSEX sur zéro ou NULL. Les éléments de classe de fenêtre sont comme indiqué dans le tableau suivant.
Élément | Objectif |
---|---|
Nom de classe | Distingue la classe des autres classes inscrites. |
Adresse de procédure de la fenêtre | Pointeur vers la fonction qui traite tous les messages envoyés aux fenêtres dans la classe et définit le comportement de la fenêtre. |
Handle d’instance | Identifie l’application ou le .dll qui a inscrit la classe. |
Curseur de classe | Définit le curseur de la souris que le système affiche pour une fenêtre de la classe . |
Icônes de classe | Définit la grande icône et la petite icône. |
Pinceau d’arrière-plan de classe | Définit la couleur et le motif qui remplissent la zone cliente lorsque la fenêtre est ouverte ou peinte. |
Menu Classe | Spécifie le menu par défaut pour les fenêtres qui ne définissent pas explicitement de menu. |
Styles de la classe | Définit comment mettre à jour la fenêtre après le déplacement ou le redimensionnement, comment traiter les double-clics de la souris, comment allouer de l’espace pour le contexte de l’appareil et d’autres aspects de la fenêtre. |
Mémoire de classe supplémentaire | Spécifie la quantité de mémoire supplémentaire, en octets, que le système doit réserver pour la classe . Toutes les fenêtres de la classe partagent la mémoire supplémentaire et peuvent l’utiliser à n’importe quel usage défini par l’application. Le système initialise cette mémoire à zéro. |
Mémoire de fenêtre supplémentaire | Spécifie la quantité de mémoire supplémentaire, en octets, que le système doit réserver pour chaque fenêtre appartenant à la classe . La mémoire supplémentaire peut être utilisée pour n’importe quel objectif défini par l’application. Le système initialise cette mémoire à zéro. |
Nom de la classe
Chaque classe de fenêtre a besoin d’un nom de classe pour distinguer une classe d’une autre. Attribuez un nom de classe en définissant le membre lpszClassName de la structure WNDCLASSEX sur l’adresse d’une chaîne terminée par null qui spécifie le nom. Étant donné que les classes de fenêtre sont spécifiques au processus, les noms de classes de fenêtre doivent être uniques uniquement au sein du même processus. En outre, étant donné que les noms de classes occupent de l’espace dans la table atom privée du système, vous devez conserver les chaînes de noms de classe aussi courtes que possible.
La fonction GetClassName récupère le nom de la classe à laquelle appartient une fenêtre donnée.
Adresse de procédure de la fenêtre
Chaque classe a besoin d’une adresse de procédure de fenêtre pour définir le point d’entrée de la procédure de fenêtre utilisée pour traiter tous les messages pour les fenêtres de la classe . Le système transmet des messages à la procédure lorsqu’il nécessite que la fenêtre effectue des tâches, telles que la peinture de sa zone cliente ou la réponse aux entrées de l’utilisateur. Un processus affecte une procédure de fenêtre à une classe en copiant son adresse vers le membre lpfnWndProc de la structure WNDCLASSEX . Pour plus d’informations, consultez Window Procedures.
Handle d’instance
Chaque classe de fenêtre nécessite un handle de instance pour identifier l’application ou .dll qui a inscrit la classe. Le système nécessite instance handles pour effectuer le suivi de tous les modules. Le système affecte un handle à chaque copie d’un exécutable ou d’un .dll en cours d’exécution.
Le système transmet un handle instance à la fonction de point d’entrée de chaque exécutable (voir WinMain) et .dll (voir DllMain). L’exécutable ou le .dll attribue ce handle instance à la classe en le copiant vers le membre hInstance de la structure WNDCLASSEX.
Curseur de classe
Le curseur de classe définit la forme du curseur lorsqu’il se trouve dans la zone cliente d’une fenêtre de la classe . Le système définit automatiquement le curseur sur la forme donnée lorsque le curseur entre dans la zone cliente de la fenêtre et s’assure qu’il conserve cette forme pendant qu’elle reste dans la zone cliente. Pour affecter une forme de curseur à une classe de fenêtre, chargez une forme de curseur prédéfinie à l’aide de la fonction LoadCursor , puis affectez la poignée de curseur retournée au membre hCursor de la structure WNDCLASSEX . Vous pouvez également fournir une ressource de curseur personnalisée et utiliser la fonction LoadCursor pour la charger à partir des ressources de l’application.
Le système ne nécessite pas de curseur de classe. Si une application définit le membre hCursor de la structure WNDCLASSEX sur NULL, aucun curseur de classe n’est défini. Le système suppose que la fenêtre définit la forme du curseur chaque fois que le curseur se déplace dans la fenêtre. Une fenêtre peut définir la forme du curseur en appelant la fonction SetCursor chaque fois que la fenêtre reçoit le message WM_MOUSEMOVE . Pour plus d’informations sur les curseurs, consultez Curseurs.
Icônes de classe
Une icône de classe est une image que le système utilise pour représenter une fenêtre d’une classe particulière. Une application peut avoir deux icônes de classe : une grande et une petite. Le système affiche l’icône de classe volumineuse d’une fenêtre dans la fenêtre de commutateur de tâches qui s’affiche lorsque l’utilisateur appuie sur ALT+TAB, ainsi que dans les grandes icônes de la barre des tâches et de l’Explorateur. La petite icône de classe apparaît dans la barre de titre d’une fenêtre et dans les petites icônes de la barre des tâches et de l’Explorateur.
Pour affecter une icône petite et grande à une classe de fenêtre, spécifiez les handles des icônes dans les membres hIcon et hIconSm de la structure WNDCLASSEX . Les dimensions de l’icône doivent être conformes aux dimensions requises pour les grandes et petites icônes de classe. Pour une grande icône de classe, vous pouvez déterminer les dimensions requises en spécifiant les valeurs SM_CXICON et SM_CYICON dans un appel à la fonction GetSystemMetrics . Pour une petite icône de classe, spécifiez les valeurs SM_CXSMICON et SM_CYSMICON . Pour plus d’informations, consultez Icônes.
Si une application définit les membres hIcon et hIconSm de la structure WNDCLASSEX sur NULL, le système utilise l’icône d’application par défaut comme grandes et petites icônes de classe pour la classe window. Si vous spécifiez une grande icône de classe, mais pas une petite, le système crée une petite icône de classe basée sur la grande. Toutefois, si vous spécifiez une petite icône de classe, mais pas une grande, le système utilise l’icône d’application par défaut comme icône de classe grande et l’icône spécifiée comme icône de classe petite.
Vous pouvez remplacer l’icône de classe grande ou petite pour une fenêtre particulière à l’aide du message WM_SETICON . Vous pouvez récupérer l’icône de classe grande ou petite actuelle à l’aide du message WM_GETICON .
Pinceau d’arrière-plan de classe
Un pinceau d’arrière-plan de classe prépare la zone cliente d’une fenêtre pour le dessin suivant par l’application. Le système utilise le pinceau pour remplir la zone cliente d’une couleur ou d’un motif unie, supprimant ainsi toutes les images précédentes de cet emplacement, qu’elles appartiennent ou non à la fenêtre. Le système avertit une fenêtre que son arrière-plan doit être peint en envoyant le message WM_ERASEBKGND à la fenêtre. Pour plus d’informations, consultez Pinceaux.
Pour affecter un pinceau d’arrière-plan à une classe, créez un pinceau à l’aide des fonctions GDI appropriées et affectez la poignée de pinceau retournée au membre hbrBackground de la structure WNDCLASSEX .
Au lieu de créer un pinceau, une application peut définir le membre hbrBackground sur l’une des valeurs de couleur système standard. Pour obtenir la liste des valeurs de couleur système standard, consultez SetSysColors.
Pour utiliser une couleur système standard, l’application doit augmenter la valeur de la couleur d’arrière-plan d’un. Par exemple, COLOR_BACKGROUND + 1 est la couleur d’arrière-plan du système. Vous pouvez également utiliser la fonction GetSysColorBrush pour récupérer un handle sur un pinceau qui correspond à une couleur système standard, puis spécifier le handle dans le membre hbrBackground de la structure WNDCLASSEX .
Le système n’exige pas qu’une classe de fenêtre ait un pinceau d’arrière-plan de classe. Si ce paramètre a la valeur NULL, la fenêtre doit peindre son propre arrière-plan chaque fois qu’elle reçoit le message WM_ERASEBKGND .
Menu Classe
Un menu de classe définit le menu par défaut à utiliser par les fenêtres de la classe si aucun menu explicite n’est fourni lors de la création des fenêtres. Un menu est une liste de commandes à partir desquelles un utilisateur peut choisir des actions que l’application doit exécuter.
Vous pouvez affecter un menu à une classe en définissant le membre lpszMenuName de la structure WNDCLASSEX sur l’adresse d’une chaîne terminée par null qui spécifie le nom de ressource du menu. Le menu est supposé être une ressource dans l’application donnée. Le système charge automatiquement le menu quand il est nécessaire. Si la ressource de menu est identifiée par un entier et non par un nom, l’application peut définir le membre lpszMenuName sur cet entier en appliquant la macro MAKEINTRESOURCE avant d’attribuer la valeur.
Le système ne nécessite pas de menu de classe. Si une application définit le membre lpszMenuName de la structure WNDCLASSEX sur NULL, les fenêtres de la classe n’ont pas de barres de menus. Même si aucun menu de classe n’est fourni, une application peut toujours définir une barre de menus pour une fenêtre lorsqu’elle crée la fenêtre.
Si un menu est fourni pour une classe et qu’une fenêtre enfant de cette classe est créée, le menu est ignoré. Pour plus d’informations, consultez Menus.
Styles de la classe
Les styles de classe définissent des éléments supplémentaires de la classe window. Deux styles ou plus peuvent être combinés à l’aide de l’opérateur OR au niveau du bit (|). Pour affecter un style à une classe de fenêtre, affectez le style au membre de style de la structure WNDCLASSEX . Pour obtenir la liste des styles de classe, consultez Styles de classe de fenêtre.
Classes et contextes d’appareil
Un contexte d’appareil est un ensemble spécial de valeurs que les applications utilisent pour dessiner dans la zone cliente de leurs fenêtres. Le système nécessite un contexte d’appareil pour chaque fenêtre sur l’écran, mais il permet une certaine flexibilité dans la façon dont le système stocke et traite ce contexte d’appareil.
Si aucun style de contexte d’appareil n’est explicitement donné, le système suppose que chaque fenêtre utilise un contexte d’appareil récupéré à partir d’un pool de contextes gérés par le système. Dans ce cas, chaque fenêtre doit récupérer et initialiser le contexte de l’appareil avant la peinture et le libérer après la peinture.
Pour éviter de récupérer un contexte d’appareil chaque fois qu’il doit peindre à l’intérieur d’une fenêtre, une application peut spécifier le style CS_OWNDC pour la classe window. Ce style de classe indique au système de créer un contexte d’appareil privé, c’est-à-dire d’allouer un contexte d’appareil unique pour chaque fenêtre de la classe. L’application n’a besoin de récupérer le contexte qu’une seule fois, puis de l’utiliser pour toutes les peintures suivantes.
Mémoire de classe supplémentaire
Le système gère une structure WNDCLASSEX en interne pour chaque classe de fenêtre du système. Lorsqu’une application inscrit une classe de fenêtre, elle peut demander au système d’allouer et d’ajouter un certain nombre d’octets de mémoire supplémentaires à la fin de la structure WNDCLASSEX . Cette mémoire est appelée mémoire de classe supplémentaire et est partagée par toutes les fenêtres appartenant à la classe . Utilisez la mémoire de classe supplémentaire pour stocker toutes les informations relatives à la classe .
Étant donné que la mémoire supplémentaire est allouée à partir du tas local du système, une application doit utiliser la mémoire de classe supplémentaire avec parcimonie. La fonction RegisterClassEx échoue si la quantité de mémoire de classe supplémentaire demandée est supérieure à 40 octets. Si une application nécessite plus de 40 octets, elle doit allouer sa propre mémoire et stocker un pointeur vers la mémoire dans la mémoire de classe supplémentaire.
Les fonctions SetClassWord et SetClassLong copient une valeur dans la mémoire de classe supplémentaire. Pour récupérer une valeur à partir de la mémoire de classe supplémentaire, utilisez les fonctions GetClassWord et GetClassLong . Le membre cbClsExtra de la structure WNDCLASSEX spécifie la quantité de mémoire de classe supplémentaire à allouer. Une application qui n’utilise pas de mémoire de classe supplémentaire doit initialiser le membre cbClsExtra sur zéro.
Mémoire de fenêtre supplémentaire
Le système gère une structure de données interne pour chaque fenêtre. Lors de l’inscription d’une classe de fenêtre, une application peut spécifier un nombre d’octets de mémoire supplémentaires, appelés mémoire de fenêtre supplémentaire. Lors de la création d’une fenêtre de la classe, le système alloue et ajoute la quantité spécifiée de mémoire de fenêtre supplémentaire à la fin de la structure de la fenêtre. Une application peut utiliser cette mémoire pour stocker des données spécifiques à une fenêtre.
Étant donné que la mémoire supplémentaire est allouée à partir du tas local du système, une application doit utiliser la mémoire de fenêtre supplémentaire avec parcimonie. La fonction RegisterClassEx échoue si la quantité de mémoire de fenêtre supplémentaire demandée est supérieure à 40 octets. Si une application nécessite plus de 40 octets, elle doit allouer sa propre mémoire et stocker un pointeur vers la mémoire dans la mémoire de la fenêtre supplémentaire.
La fonction SetWindowLong copie une valeur dans la mémoire supplémentaire. La fonction GetWindowLong récupère une valeur à partir de la mémoire supplémentaire. Le membre cbWndExtra de la structure WNDCLASSEX spécifie la quantité de mémoire de fenêtre supplémentaire à allouer. Une application qui n’utilise pas la mémoire doit initialiser cbWndExtra à zéro.