Sous-classement de contrôles avec une procédure de fenêtre managée
Mise à jour : novembre 2007
Le .NET Compact Framework permet au code natif d'appeler le code managé à l'aide d'un délégué de rappel. En sous-classant un contrôle managé pour recevoir un rappel provenant de son contrôle natif correspondant, vous pouvez créer des contrôles avec des fonctionnalités qui ne sont pas disponibles directement dans le .NET Compact Framework.
Cette rubrique avancée s'adresse aux développeurs maîtrisant la programmation sous Windows et le sous-classement de contrôle. Pour sous-classer un contrôle, vous devrez connaître les détails propres au contrôle natif et son mappage aux fonctionnalités à fournir dans l'extension du contrôle managé. Vous devrez connaître les messages Windows à surveiller, ainsi que les fonctions de Windows Embedded CE natives à appeler pour obtenir les fonctionnalités souhaitées.
Cette rubrique décrit le sous-classement des contrôles TreeView et Button. Les rubriques suivantes fournissent les exemples de code et les instructions de génération des applications.
Rubrique Comment |
Illustrations |
---|---|
Comment : sous-classer un contrôle TreeView à l'aide de rappels natifs |
Sous-classement du contrôle TreeView pour créer une implémentation de l'événement NodeMouseClick. Le .NET Compact Framework ne prend pas en charge cette méthode directement, car sa taille doit être réduite pour les ressources limitées. |
Comment : sous-classer un contrôle Button à l'aide de rappels natifs |
Sous-classement du contrôle Button pour afficher un remplissage dégradé coloré. Notez que ce bouton est fourni à l'origine pour illustrer l'utilisation du sous-classement et des rappels. Pour créer facilement un bouton avec un remplissage dégradé, consultez Comment : afficher un remplissage dégradé. |
Ces deux programmes de sous-classement incluent la classe WndProcHooker et une classe d'assistance de structures Win32 natives, les déclarations d'appel de plateforme, ainsi qu'un délégué WndProc. Pour obtenir les listes de code, consultez Comment : utiliser une classe pour raccorder des procédures Windows et Comment : utiliser une classe d'assistance pour les appels de plates-formes.
Classe WndProcHooker
La classe WndProcHooker permet à un contrôle natif, ou à une fenêtre, d'appeler un rappel de code managé lorsqu'un message Windows particulier est reçu pour ce contrôle. Cette opération est réalisée en remplaçant une procédure de fenêtre d'un contrôle natif (WndProc) par une procédure de fenêtre générique, WindowProc, qui exécute une recherche afin de déterminer si le contrôle fait partie d'une liste de contrôles associés aux méthodes de rappel à appeler. Si tel est le cas, le contrôle doit être raccordé.
Si le contrôle est raccordé, WindowProc détermine si le contrôle est mappé pour répondre à un message Windows particulier. C'est la table des messages qui mappe un message Windows à un délégué WndProcCallback qui appelle votre méthode managée contenant les fonctionnalités souhaitées. Si la table des messages contient le message, le délégué WndProcCallback appelle votre code à l'aide des paramètres de message qui ont été fournis à WindowProc.
Raccordement de contrôles
La méthode HookWndProc associe le handle du contrôle à une table des messages devant être utilisée par la procédure de fenêtre générique WindowProc. Cette opération est appelée raccordement d'un contrôle.
La méthode HookWndProc détermine si un contrôle a déjà été raccordé. Si ce n'est pas le cas, elle crée un objet HookedProcInformation pour ce contrôle. Cet objet contient une référence au contrôle et à la table des messages. Si le handle du contrôle a déjà été créé, il raccorde la fenêtre en créant un pointeur vers la procédure d'origine de la fenêtre pour une restauration ultérieure. Si le handle n'a pas été créé, il sera raccordé par la méthode ctrl_HandleCreated qui gère l'événement HandleCreated.
Ensuite, la méthode HookWndProc ajoute l'objet HookedProcInformation à l'une des deux collections de dictionnaires génériques :
Le dictionnaire hwindDict, qui contient une liste globale de tous les handles de fenêtres raccordés. La clé est un hwnd. Les contrôles dont les handles ont été créés entrent dans ce dictionnaire. Les contrôles de ce dictionnaire sont évalués par WindowProc pour tous les messages mappés.
Dictionnaire ctlDict , qui contient des contrôles dont les handles n'ont pas été créés. Lorsque la méthode ctrl_HandleCreated est appelée, le contrôle est déplacé dans le dictionnaire hwndDict.
Décrochage de contrôles
La méthode UnhookWndProc propose deux façons de décrocher un contrôle :
Supprimez un message de la table des messages pour un contrôle, mais conservez toutefois le contrôle dans le dictionnaire des fenêtres raccordées hwndDict. Cette méthode restaure également la procédure de fenêtre d'origine pour le contrôle en utilisant un pointeur conservé dans l'objet HookedProcInformation.
Supprimez le contrôle du dictionnaire hwndDict de contrôles raccordés, puis supprimez son handle et placez-le dans le dictionnaire ctrlDict ou supprimez complètement le contrôle. Cette méthode restaure également la procédure de fenêtre d'origine pour le contrôle en utilisant un handle conservé dans l'objet HookedProcInformation.
Sous-classement du contrôle TreeView
La classe de l'exemple de programme TreeViewBonus, répertoriée dans Comment : sous-classer un contrôle TreeView à l'aide de rappels natifs, étend le contrôle TreeView pour inclure l'événement NodeMouseClick, qui n'est pas disponible directement dans le .NET Compact Framework.
L'événement NodeMouseClick est obtenu en ajoutant le message WM_NOTIFY à la table des messages pour le contrôle, tel que l'exécute la classe WndProcHooker. La méthode de rappel managé WM_Notify_Handler appelle la fonction native GetMessagePos pour obtenir les coordonnées du pointeur de souris au moment de l'envoi des messages Windows.
Notez que ces coordonnées sont relatives à la zone cliente visible à l'écran, et non au contrôle TreeView. La classe TreeViewBonus convertit les coordonnées d'écran en coordonnées clientes à l'aide de la méthode PointToClient pour le contrôle. Ensuite, ces coordonnées clientes sont envoyées avec le message TVM_HITTEST pour déterminer si l'objet TreeViewBonus a été activé et à quel endroit.
La classe TreeViewBonus contient le code pour obtenir les coordonnées relatives au contrôle à l'aide du message TVM_HITTEST du contrôle natif.
Si le clic s'est produit sur l'un des nœuds de l'arborescence, la structure TVHITTESTINFO native contient le handle de ce nœud. La dernière étape consiste à parcourir de manière récursive les nœuds TreeView managés, à l'aide de la méthode FindTreeNodeFromHandle, afin de rechercher le handle correspondant et de déclencher l'événement NodeMouseClick. La classe TreeNodeMouseClickEventArgs fournit les données suivantes :
Nœud activé.
Bouton sur lequel l'utilisateur a cliqué.
Nombre de clics, dont la valeur est 1.
Coordonnée x où le clic s'est produit.
Coordonnée y où le clic s'est produit.
La classe TreeViewBonus raccorde le parent du contrôle de l'arborescence natif à une procédure de fenêtre managée, tel que l'exécute la classe WndProcHooker. Elle répond à l'événement OnParentChanged en raccordant le contrôle parent, prenant ainsi en compte que TreeView ait pu être déplacé vers un nouveau parent, tel qu'à partir du Form vers le Panel.
Sous-classement du contrôle Button
Les classes GradientFilledButton et GradientFill répertoriées dans Comment : sous-classer un contrôle Button à l'aide de rappels natifs étendent le contrôle Button pour afficher un remplissage dégradé entre deux couleurs. À l'origine, ce programme est destiné à illustrer le sous-classement. Toutefois, une façon plus facile d'afficher un remplissage dégradé dans un bouton consiste à créer un contrôle personnalisé dérivé de Control, comme décrit dans Comment : afficher un remplissage dégradé.
Le constructeur pour la classe GradientFilledButton crée des instances de la classe WndProcHooker pour mapper des messages Windows aux rappels managés. Ces méthodes de rappel dessinent le bouton de manière appropriée en fonction du message Windows et de l'état de la propriété Capture pour le contrôle. Le tableau suivant répertorie les messages Windows mappés et leurs rappels correspondants.
Message Windows |
Méthode de rappel managé et description |
---|---|
WM_KEYDOWN |
WM_KeyDown_Handler : redessine le bouton à l'état actif lorsque l'utilisateur appuie sur la touche ESPACE ou ENTRÉE (ou Action). |
WM_KEYUP |
WM_KeyUp_Handler : redessine le bouton à l'état inactif et déclenche l'événement Click si l'utilisateur appuie sur la touche ESPACE ou ENTRÉE (Action). |
WM_LBUTTONDOWN |
WM_LeftButtonDown_Hander : redessine le bouton à l'état actif et attribue la valeur true à la propriété de la souris Capture pour le contrôle. |
WM_LBUTTONUP |
WM_LButtonUp_Handler : redessine le bouton à l'état inactif, déclenche l'événement MouseUp si le curseur est relâché dans la zone cliente du contrôle et attribue la valeur false à la propriété de la souris Capture pour le contrôle. |
WM_MOUSEMOVE |
WM_MouseMove_Handler : redessine le bouton s'il a été activé précédemment et si Capture a la valeur true. |
WM_PAINT |
WM_Paint_Handler : redessine le bouton de manière appropriée. |
Ces méthodes de rappel managé utilisent la méthode DrawButton pour dessiner le bouton de manière appropriée. Cette méthode possède deux surcharges pour dessiner le bouton sur une fenêtre, comme dans cet exemple, ou sur un objet Graphics. Les deux surcharges adoptent la valeur Boolean true si le bouton a été activé.
La classe GradientFilledButton utilise la classe GradientFill pour exécuter les appels de plateforme dans le code natif afin de réaliser le remplissage. La classe GradientFill fournit les propriétés de définition des couleurs de début et de fin, ainsi que les propriétés du sens de remplissage, tel que de gauche à droite ou de haut en bas.
Voir aussi
Tâches
Comment : utiliser une classe pour raccorder des procédures Windows
Comment : utiliser une classe d'assistance pour les appels de plates-formes
Comment : sous-classer un contrôle TreeView à l'aide de rappels natifs
Comment : afficher un remplissage dégradé
Concepts
.Rubriques Comment relatives au .NET Compact Framework