À propos des procédures de fenêtre
Chaque fenêtre est membre d’un classement de fenêtre particulière. Le classement de fenêtre détermine la procédure de fenêtre par défaut utilisée par une fenêtre individuelle pour traiter ses messages. Toutes les fenêtres appartenant au même classement utilisent la même procédure de fenêtre par défaut. Par exemple, le système définit une procédure de fenêtre pour le classement de zone de liste modifiable (zone de liste modifiable); toutes les zones de liste modifiable utilisent ensuite cette procédure de fenêtre.
Une application inscrit généralement au moins un nouveau classement de fenêtre et sa procédure de fenêtre associée. Après avoir inscrit une classe, l’application peut créer de nombreuses fenêtres de cette classe, qui utilisent toutes la même procédure de fenêtre. Comme cela signifie que plusieurs sources peuvent appeler simultanément le même morceau de code, vous devez être prudent lorsque vous modifiez des ressources partagées à partir d’une procédure de fenêtre. Pour plus d’informations, consultez Classes Window.
Les procédures de fenêtre pour les boîtes de dialogue (appelées procédures de boîte de dialogue) ont une structure et une fonction similaires à celles des procédures de fenêtre normales. Tous les points faisant référence aux procédures de fenêtre de cette section s’appliquent également aux procédures de boîte de dialogue. Pour plus d’informations, consultez Boîtes de dialogue.
Cette section décrit les rubriques suivantes.
- Structure d’une procédure de fenêtre
- Procédure de fenêtre par défaut
- Sous-classement de procédure de fenêtre
- Superclassement de procédure de fenêtre
Structure d’une procédure de fenêtre
Une procédure de fenêtre est une fonction qui a quatre paramètres et retourne une valeur signée. Les paramètres se composent d’un handle de fenêtre, d’un identificateur de message UINT et de deux paramètres de message déclarés avec les types de données WPARAM et LPARAM. Pour plus d’informations, consultez WindowProc.
Les paramètres de message contiennent souvent des informations dans leurs mots de bas ordre et de classement élevé. Il existe plusieurs macros qu’une application peut utiliser pour extraire des informations des paramètres de message. La macro LOWORD, par exemple, extrait le mot de bas ordre (bits 0 à 15) à partir d’un paramètre de message. D’autres macros incluent HIWORD, LOBYTE et la macro HIBYTE.
L’interprétation de la valeur de retour dépend du message particulier. Consultez la description de chaque message pour déterminer la valeur de retour appropriée.
Étant donné qu’il est possible d’appeler une procédure de fenêtre de manière récursive, il est important de réduire le nombre de variables locales qu’elle utilise. Lors du traitement de messages individuels, une application doit appeler des fonctions en dehors de la procédure de la fenêtre afin d’éviter l’utilisation excessive de variables locales, ce qui pourrait entraîner un débordement de la pile lors d’une récursion profonde.
Procédure de fenêtre par défaut
La fonction de procédure de fenêtre par défaut, DefWindowProc définit un comportement fondamental partagé par toutes les fenêtres. La procédure de fenêtre par défaut fournit les fonctionnalités minimales d’une fenêtre. Une procédure de fenêtre définie par l’application doit transmettre les messages qu’elle ne traite pas à la fonction DefWindowProc pour le traitement par défaut.
Sous-classement de procédure de fenêtre
Lorsqu’une application crée une fenêtre, le système alloue un bloc de mémoire pour stocker les informations spécifiques à la fenêtre, y compris l’adresse de la procédure de fenêtre qui traite les messages pour la fenêtre. Lorsque le système doit transmettre un message à la fenêtre, il recherche dans les informations spécifiques à la fenêtre l’adresse de la procédure de la fenêtre et transmet le message à cette procédure.
La sous-classe est une technique qui permet à une application d’intercepter et de traiter les messages envoyés ou publiés dans une fenêtre particulière avant que la fenêtre ait la possibilité de les traiter. En sous-classant une fenêtre, une application peut augmenter, modifier ou surveiller le comportement de la fenêtre. Une application peut sous-classer une fenêtre appartenant à un classement global système, telle qu’un contrôle d’édition ou une zone de liste. Par exemple, une application peut sous-classer un contrôle d’édition pour empêcher le contrôle d’accepter certains caractères. Toutefois, vous ne pouvez pas sous-classer une fenêtre ou un classement qui appartient à une autre application. Tous les sous-classements doivent être effectués dans le même processus.
Un sous-classement d’application une fenêtre en remplaçant l’adresse de la procédure de fenêtre d’origine de la fenêtre par l’adresse d’une nouvelle procédure de fenêtre, appelée procédure de sous-classe. Par la suite, la procédure de sous-classement reçoit tous les messages envoyés ou publiés dans la fenêtre.
La procédure de sous-classement peut effectuer trois actions lorsqu’elle reçoit un message : elle peut transmettre le message à la procédure de fenêtre d’origine, modifier le message et le transmettre à la procédure de fenêtre d’origine, ou traiter le message et ne pas le transmettre à la procédure de fenêtre d’origine. Si la procédure de sous-classement traite un message, elle peut le faire avant, après ou après, avant et après qu’elle passe le message à la procédure de fenêtre d’origine.
Le système fournit deux types de sous-classement : instance et global. Dans le sous-classement d’instance, une application remplace l’adresse de procédure de fenêtre d’une seule instance d’une fenêtre. Une application doit utiliser le sous-classement d’instance pour sous-classer une fenêtre existante. Dans le sous-classement global, une application remplace l’adresse de la procédure de fenêtre dans la structure WNDCLASSEX d’une classe de fenêtre. Toutes les fenêtres suivantes créées avec le classement ont l’adresse de la procédure de sous-classement, mais les fenêtres existantes du classement ne sont pas affectées.
Sous-classement d’instance
Une application sous-classe une instance d’une fenêtre à l’aide de la fonction SetWindowLongPtr. L’application transmet l’indicateur GWL_WNDPROC, le handle à la fenêtre à sous-classer et l’adresse de la procédure de sous-classement à SetWindowLongPtr. La procédure de sous-classement peut résider dans l’exécutable de l’application ou dans une DLL.
Une fois que l’indicateur GWL_WNDPROC a été transmis, SetWindowLongPtr retourne l’adresse de la procédure de fenêtre d’origine. L’application doit enregistrer cette adresse, et l’utiliser dans les appels ultérieurs à la fonction CallWindowProc, pour transmettre les messages interceptés à la procédure de fenêtre d’origine. L’application doit également avoir l’adresse de procédure de fenêtre d’origine pour supprimer le sous-classement de la fenêtre. Pour supprimer la sous-classe, l’application appelle à nouveau SetWindowLongPtr, en transmettant l’adresse de la procédure de fenêtre d’origine avec l’indicateur GWL_WNDPROC et le handle à la fenêtre.
Le système possède les classements globaux système et les aspects des contrôles peuvent passer d’une version du système à l’autre. Si l’application doit sous-classer une fenêtre appartenant à un classement global système, le développeur peut avoir besoin de mettre à jour l’application lorsqu’une nouvelle version du système est publiée.
Étant donné que le sous-classement d’instance se produit après la création d’une fenêtre, vous ne pouvez pas ajouter d’octets supplémentaires à la fenêtre. Les applications qui sous-classent une fenêtre doivent utiliser la liste de propriétés de la fenêtre pour stocker les données nécessaires pour une instance de la fenêtre sous-classée. Pour plus d’informations, consultez Propriétés de la fenêtre.
Lorsqu’une application sous-classée une fenêtre sous-classée, elle doit supprimer les sous-classements dans l’ordre inverse qu’elles ont été effectuées. Si l’ordre de suppression n’est pas inversé, une erreur système irrécupérable peut se produire.
Sous-classement global
Pour sous-classer globalement un classement de fenêtre, l’application doit avoir un handle vers une fenêtre du classement. L’application a également besoin du handle pour supprimer le sous-classement. Pour obtenir le handle, une application crée généralement une fenêtre masquée du classement au sous-classement. Après avoir obtenu le handle, l’application appelle la fonction SetClassLongPtr, en précisant le handle, l’indicateur GCL_WNDPROC et l’adresse de la procédure de sous-classement. SetClassLongPtr renvoie l’adresse de la procédure de fenêtre d’origine de la classe.
L’adresse de procédure de fenêtre d’origine est utilisée dans le sous-classement global de la même façon qu’elle est utilisée dans le sous-classement d’instance. La procédure de sous-classement transmet les messages à la procédure de fenêtre d’origine en appelant CallWindowProc. L’application supprime la sous-classe de la classe de fenêtre en appelant à nouveau SetClassLongPtr, en précisant l’adresse de la procédure de fenêtre d’origine, l’indicateur GCL_WNDPROC et le handle à une fenêtre de la classe qui est en cours de sous-classement. Une application qui sous-classe globalement un classement de contrôle doit supprimer le sous-classement lorsque l’application se termine; sinon, une erreur système irrécupérable peut se produire.
Le sous-classement global présente les mêmes limitations que le sous-classement d’instance, ainsi que certaines restrictions supplémentaires. Une application ne doit pas utiliser les octets supplémentaires pour le classement ou l’instance de fenêtre sans savoir exactement comment la procédure de fenêtre d’origine les utilise. Si l’application doit associer des données à une fenêtre, elle doit utiliser les propriétés de fenêtre.
Superclassement de procédure de fenêtre
Superclassement est une technique qui permet à une application de créer un classement de fenêtre avec les fonctionnalités de base du classement existant, ainsi que les améliorations fournies par l’application. Un superclassement est basé sur un classement de fenêtre existant appelée classement de base. Souvent, le classement de base est un classement de fenêtre globale système telle qu’un contrôle d’édition, mais il peut s’agir de n’importe quel classement de fenêtre.
Un superclassement a sa propre procédure de fenêtre, appelée procédure de superclassement. La procédure de superclassement peut effectuer trois actions lorsqu’elle reçoit un message : elle peut transmettre le message à la procédure de fenêtre d’origine, modifier le message et le transmettre à la procédure de fenêtre d’origine, ou traiter le message et ne pas le transmettre à la procédure de fenêtre d’origine. Si la procédure de superclassement traite un message, elle peut le faire avant, après ou après, avant et après qu’elle passe le message à la procédure de fenêtre d’origine.
Contrairement à une procédure de sous-classement, une procédure de superclassement peut traiter les messages de création de fenêtre (WM_NCCREATE, WM_CREATE, et ainsi de suite), mais elle doit également les transmettre à la procédure de fenêtre de classement de base d’origine afin que la procédure de fenêtre de classement de base puisse effectuer sa procédure d’initialisation.
Pour surclasser une classe de fenêtre, une application appelle d’abord la fonction GetClassInfoEx pour récupérer les informations relatives à la classe de base. GetClassInfoEx remplit une structure WNDCLASSEX avec les valeurs de la structure WNDCLASSEX de la classe de base. Ensuite, l’application copie son propre handle d’instance dans le membre hInstance de la structure WNDCLASSEX et copie le nom de la superclasse dans le membre lpszClassName. Si le classement de base possède un menu, l’application doit fournir un nouveau menu avec les mêmes identificateurs de menu et copier le nom du menu dans le membre lpszMenuName. Si la procédure superclasse traite le message WM_COMMAND et ne la transmet pas à la procédure de fenêtre du classement de base, le menu n’a pas besoin d’identificateurs correspondants. GetClassInfoEx ne renvoie pas le membre lpszMenuName, lpszClassName, ou hInstance de la structure WNDCLASSEX.
Une application doit également définir le membre lpfnWndProc de la structure WNDCLASSEX. La fonction GetClassInfoEx renseigne ce membre avec l’adresse de la procédure de fenêtre d’origine de la classe. L’application doit enregistrer cette adresse pour transmettre des messages à la procédure de fenêtre d’origine, puis copier l’adresse de la procédure de superclassement dans le membre lpfnWndProc. Si nécessaire, l’application peut modifier tous les autres membres de la structure WNDCLASSEX. Une fois qu’elle a rempli la structure WNDCLASSEX, l’application enregistre la superclasse en transmettant l’adresse de la structure à la fonction RegisterClassEx. Le superclassement peut ensuite être utilisé pour créer des fenêtres.
Étant donné que le superclassement inscrit un nouveau classement de fenêtre, une application peut ajouter à la fois les octets de classements supplémentaires et les octets de fenêtre supplémentaires. Le superclassement ne doit pas utiliser les octets supplémentaires d’origine pour le classement de base ou la fenêtre pour les mêmes raisons qu’un sous-classement d’instance ou un sous-classement global ne doit pas les utiliser. En outre, si l’application ajoute des octets supplémentaires pour son utilisation au classement ou à l’instance de fenêtre, elle doit référencer les octets supplémentaires par rapport au nombre d’octets supplémentaires utilisés par le classement de base d’origine. Étant donné que le nombre d’octets utilisés par le classement de base peut varier d’une version du classement de base à la suivante, le décalage de départ pour les propres octets supplémentaires du superclassement peut également varier d’une version du classement de base à la suivante.