Partage de boucles de messages entre Win32 et WPF
Mise à jour : novembre 2007
Cette rubrique décrit comment implémenter une boucle de messages pour l'interopérabilité avec Windows Presentation Foundation (WPF), en utilisant l'exposition de boucle de messages existante dans Dispatcher ou en créant une boucle de messages séparée du côté Win32 de votre code d'interopérabilité.
ComponentDispatcher et la boucle de messages
Un scénario normal pour l'interopérabilité et la prise en charge d'événement clavier consiste à implémenter IKeyboardInputSink ou à sous-classer à partir de classes qui implémentent déjà IKeyboardInputSink, telles que HwndSource ou HwndHost. Toutefois, la prise en charge du récepteur du clavier ne traite pas tous les besoins de la boucle de messages que vous pouvez rencontrer lors de l'envoi et de la réception de messages à travers vos limites d'interopérabilité. Afin d'aider à formaliser une architecture de boucle de messages d'application, Windows Presentation Foundation (WPF) fournit la classe ComponentDispatcher, qui définit un protocole simple pour une boucle de messages à suivre.
ComponentDispatcher est une classe statique qui expose plusieurs membres. La portée de chaque méthode est liée implicitement au thread appelant. Une boucle de messages doit appeler certaines de ces API à des moments critiques (comme défini dans la section suivante).
ComponentDispatcher fournit des événements que d'autres composants (tel que le récepteur de clavier) peuvent écouter. La classe Dispatcher appelle toutes les méthodes ComponentDispatcher appropriées dans une séquence appropriée. Si vous implémentez votre propre boucle de messages, votre code est chargé d'appeler des méthodes ComponentDispatcher de façon similaire.
L'appel de méthodes ComponentDispatcher sur un thread n'appellera que les gestionnaires d'événements enregistrés sur ce thread.
Écriture de boucles de messages
Les éléments suivants sont une liste de contrôle des membres ComponentDispatcher que vous utiliserez si vous écrivez votre propre boucle de messages :
PushModal : Méthode que votre boucle de messages doit appeler pour indiquer que le thread est modal.
PopModal : Méthode que votre boucle de messages doit appeler pour indiquer que le thread a été rétabli à l'état non modal.
RaiseIdle : Méthode que votre boucle de messages doit appeler pour indiquer que ComponentDispatcher doit déclencher l'événement ThreadIdle. ComponentDispatcher ne déclenchera pas ThreadIdle si IsThreadModal est true, mais les boucles de messages peuvent choisir d'appeler RaiseIdle même si ComponentDispatcher ne peut pas y répondre pendant qu'il est à l'état modal.
RaiseThreadMessage : Méthode que votre boucle de messages doit appeler pour indiquer qu'un nouveau message est disponible. La valeur de retour indique si un écouteur d'événement ComponentDispatcher a géré le message. Si RaiseThreadMessage retourne la valeur true (géré), le répartiteur en a fini avec le message. Si la valeur de retour est false, le répartiteur est supposé appeler la fonction Win32TranslateMessage, puis appeler DispatchMessage.
Utilisation de ComponentDispatcher et gestion des messages existants
Les éléments suivants sont une liste de contrôle des membres ComponentDispatcher que vous utiliserez si vous utilisez la boucle de messages WPF inhérente.
IsThreadModal :retourne si l'application est passée en mode modal (par exemple, une boucle de messages modale a fait l'objet d'un push). ComponentDispatcher peut suivre cet état parce que la classe tient à jour un compteur des appels PushModal et PopModal de la boucle de messages.
Les événements ThreadFilterMessage et ThreadPreprocessMessage suivent les règles standards pour les appels de délégué. Les délégués sont appelés dans un ordre non spécifié et tous les délégués sont appelés même si le premier marque le message comme étant géré.
ThreadIdle :indique un moment approprié et efficace pour le traitement des temps d'inactivité (il n'y a pas d'autres messages en attente pour le thread). ThreadIdle ne sera pas déclenché si le thread est modal.
ThreadFilterMessage : déclenché pour tous les messages que la pompe de messages traite.
ThreadPreprocessMessage : déclenché pour tous les messages qui n'ont pas été gérés pendant ThreadFilterMessage.
Un message est considéré géré si après l'événement ThreadFilterMessage ou ThreadPreprocessMessage, le paramètre handled passé par référence dans les données d'événement est true. Les gestionnaires d'événements doivent ignorer le message si handled est true, parce que cela signifie que le gestionnaire différent a géré le message en premier. Les gestionnaires d'événements des deux événements peuvent modifier le message. Le répartiteur doit distribuer le message modifié plutôt que le message inchangé d'origine. ThreadPreprocessMessage est remis à tous les écouteurs, mais l'intention architecturale est que seule la fenêtre de niveau supérieur qui contient le HWND que les messages ciblent doit appeler le code en réponse au message.
Comment HwndSource traite des événements ComponentDispatcher
Si le HwndSource est une fenêtre de niveau supérieur (pas de HWND parent), il s'enregistrera avec ComponentDispatcher. Si ThreadPreprocessMessage est déclenché et si le message est prévu pour les fenêtres HwndSource ou enfants, HwndSource appelle son IKeyboardInputSink.TranslateAccelerator, TranslateChar, séquence du récepteur du clavier OnMnemonic.
Si le HwndSource n'est pas une fenêtre de niveau supérieur (possède un HWND parent), aucune gestion n'aura lieu. Seule la fenêtre de niveau supérieur est supposée effectuer la gestion, et une fenêtre de niveau supérieur est censée exister avec prise en charge du récepteur du clavier dans le cadre de tout scénario d'interopérabilité.
Si WndProc sur un HwndSource est appelé sans appel préalable d'une méthode appropriée du récepteur du clavier, votre application recevra les événements du clavier du niveau supérieur tels que KeyDown. Toutefois, aucune méthode du récepteur du clavier ne sera appelée, qui contournerait des fonctionnalités de modèle d'entrée au clavier souhaitables comme la prise en charge des touches d'accès rapide. Cela peut arriver parce que la boucle de messages n'a pas notifié correctement le thread pertinent sur le ComponentDispatcher, ou parce que le parent HWND n'a pas appelé les bonnes réponses du récepteur du clavier.
Un message qui s'adresse au récepteur du clavier ne peut pas être envoyé à HWND si vous avez ajouté des points de raccordements pour ce message en utilisant la méthode AddHook. Le message a pu être géré directement au niveau de la pompe de messages et ne pas avoir été soumis à la fonction DispatchMessage.
Voir aussi
Concepts
Vue d'ensemble de l'interopérabilité WPF et Win32