Freigeben über


Gemeinsame Verwendung von Nachrichtenschleifen zwischen Win32 und WPF

Aktualisiert: November 2007

In diesem Thema erfahren Sie, wie Sie eine Nachrichtenschleife für die Interoperation mit Windows Presentation Foundation (WPF) implementieren können, indem Sie entweder eine vorhandene Nachrichtenschleife in Dispatcher verfügbar machen oder eine separate Nachrichtenschleife auf der Win32-Seite Ihres Codes für die Interoperation erstellen.

ComponentDispatcher und Nachrichtenschleifen

Ein normales Szenario für die Interoperation und die Unterstützung von Tastaturereignissen ist die Implementierung von IKeyboardInputSink oder das Erstellen einer Unterklasse aus Klassen, die bereits IKeyboardInputSink implementieren, wie zum Beispiel HwndSource oder HwndHost. Durch die Unterstützung einer Tastatursenke werden jedoch möglicherweise nicht alle Ihre Anforderungen erfüllt, die beim Senden und Empfangen von Nachrichten über die Grenzen der Interoperation hinweg anfallen können. Um die Anwendungsarchitektur mit Nachrichtenschleifen stärker zu formalisieren, stellt Windows Presentation Foundation (WPF) die ComponentDispatcher-Klasse bereit, die ein einfaches Protokoll, dem die Nachrichtenschleife folgen muss, definiert.

ComponentDispatcher ist eine statische Klasse, die mehrere Member verfügbar macht. Der Anwendungsbereich der einzelnen Methoden ist implizit an den aufrufenden Thread gebunden. Die Nachrichtenschleife muss einige dieser APIs zu einem bestimmten Zeitpunkt (siehe nächster Abschnitt) aufrufen.

ComponentDispatcher stellt Ereignisse bereit, die von anderen Komponenten wie der Tastatursenke überwacht (abgehört) werden können. Die Dispatcher-Klasse ruft alle relevanten ComponentDispatcher-Methoden in der entsprechenden Reihenfolge auf. Falls Sie Ihre eigene Nachrichtenschleife implementieren, müssen die ComponentDispatcher-Methoden auf ähnliche Weise durch Ihren Code aufgerufen werden.

Durch den Aufruf von ComponentDispatcher-Methoden für einen Thread werden nur die Ereignishandler ausgelöst, die für diesen Thread registriert wurden.

Schreiben von Nachrichtenschleifen

Die folgenden ComponentDispatcher-Member kommen zum Einsatz, wenn Sie Ihre eigene Nachrichtenschleife schreiben:

  • PushModal: Die Nachrichtenschleife sollte diesen Member aufrufen, um anzuzeigen, dass es sich um einen modalen Thread handelt.

  • PopModal: Die Nachrichtenschleife sollte diesen Member aufrufen, um anzuzeigen, dass der Thread wieder in einen Thread ohne Modus umgewandelt wurde.

  • RaiseIdle: Die Nachrichtenschleife sollte diesen Member aufrufen, um anzuzeigen, dass ComponentDispatcher das ThreadIdle-Ereignis auslösen soll. ComponentDispatcher löst ThreadIdle nicht aus, wenn IsThreadModal auf true festgelegt ist. Nachrichtenschleifen können jedoch RaiseIdle aufrufen, auch wenn ComponentDispatcher im modalen Zustand nicht darauf reagieren kann.

  • RaiseThreadMessage: Die Nachrichtenschleife sollte diesen Member aufrufen, um anzuzeigen, dass eine neue Nachricht verfügbar ist. Der Rückgabewert zeigt an, ob die Nachricht von einem Listener für ein ComponentDispatcher-Ereignis behandelt wurde. Falls RaiseThreadMessage als Antwort true (behandelt) zurückgibt, sollte der Dispatcher keine weiteren Aktionen hinsichtlich der Nachricht durchführen. Falls der Rückgabewert false ist, muss der Dispatcher zuerst die Win32-Funktion TranslateMessage und dann DispatchMessage aufrufen.

ComponentDispatcher und bestehende Meldungsbehandlung

Die folgenden ComponentDispatcher-Member werden verwendet, wenn Sie auf die Nachrichtenschleife von WPF zurückgreifen.

  • IsThreadModal: Gibt an, ob die Anwendung in den Modalzustand versetzt wurde (zum Beispiel durch Push einer modalen Nachrichtenschleife). ComponentDispatcher kann diesen Status verfolgen, weil die Klasse die PushModal-Aufrufe und die PopModal-Aufrufe der Nachrichtenschleife zählt.

  • ThreadFilterMessage-Ereignisse und ThreadPreprocessMessage-Ereignisse folgen den Standardregeln für Delegataufrufe. Delegate werden in einer nicht vorgegebenen Reihenfolge aufgerufen, und es werden alle Delegate aufgerufen, selbst wenn die Nachricht vom ersten Delegat als behandelt gekennzeichnet wurde.

  • ThreadIdle: Zeigt einen geeigneten Zeitpunkt für die effiziente Leerlaufverarbeitung an (es gibt keine weiteren anstehenden Nachrichten für den Thread). ThreadIdle wird nicht ausgelöst, wenn sich der Thread im modalen Zustand befindet.

  • ThreadFilterMessage: Wird für alle vom Nachrichtensystem verarbeiteten Nachrichten ausgelöst.

  • ThreadPreprocessMessage: Wird für alle Nachrichten ausgelöst, die im Zuge von ThreadFilterMessage nicht behandelt wurden.

Eine Nachricht wird als behandelt angesehen, wenn im Anschluss an das ThreadFilterMessage-Ereignis oder das ThreadPreprocessMessage-Ereignis der per Referenz in den Ereignisdaten übergebene handled-Parameter true ist. Die Nachricht sollte von Ereignishandlern ignoriert werden, wenn handled den Wert true aufweist, da dies bedeutet, dass die Nachricht zuerst von einem anderen Handler behandelt wurde. Die Nachricht wird möglicherweise von den Ereignishandlern für beide Ereignisse geändert. Der Dispatcher sollte die geänderte Nachricht und nicht die ursprüngliche, unbearbeitete Nachricht senden. ThreadPreprocessMessage wird an alle Listener ausgeliefert, beabsichtigt ist in der Architektur jedoch, dass nur das Fenster auf oberster Ebene mit dem HWND, auf den die Nachrichten ausgerichtet waren, Code als Antwort auf die Nachricht aufruft.

Behandlung von ComponentDispatcher-Ereignissen durch HwndSource

Falls es sich bei HwndSource um ein Fenster auf oberster Ebene (ohne übergeordneten HWND) handelt, erfolgt die Registrierung bei ComponentDispatcher. Falls ThreadPreprocessMessage ausgelöst wird und die Nachricht für HwndSource oder untergeordnete Fenster bestimmt ist, ruft HwndSource die Tastatursenkensequenz IKeyboardInputSink.TranslateAccelerator, TranslateChar, OnMnemonic auf.

Falls es sich bei HwndSource nicht um ein Fenster auf oberster Ebene handelt (das heißt, das Fenster verfügt über einen übergeordneten HWND), findet keine Behandlung statt. Die Behandlung wird nur vom Fenster auf oberster Ebene erwartet, und es wird im Rahmen der Interoperation vorausgesetzt, dass es ein Fenster auf oberster Ebene mit Tastatursenkenunterstützung gibt.

Falls WndProc für eine HwndSource aufgerufen wird, ohne dass zuvor eine passende Tastatursenkenmethode aufgerufen wurde, empfängt Ihre Anwendung Tastaturereignisse der höheren Ebene wie zum Beispiel KeyDown. Die Tastatursenkenmethoden werden jedoch eventuell nicht aufgerufen, wodurch erwünschte Funktionen des Tastatureingabemodells wie die Unterstützung von Zugriffstasten verhindert werden. Dies kann vorkommen, wenn der entsprechende Thread auf dem ComponentDispatcher nicht richtig von der Nachrichtenschleife benachrichtigt wurde oder wenn der übergeordnete HWND nicht die richtigen Tastatursenkenantworten aufgerufen hat.

Eine an die Tastatursenke gelieferte Nachricht wird unter Umständen nicht an den HWND gesendet, wenn Sie mit der AddHook-Methode Hooks für diese Nachricht hinzugefügt haben. Eventuell wurde die Nachricht direkt auf Nachrichtensystemebene behandelt und nicht an die DispatchMessage-Funktion übergeben.

Siehe auch

Konzepte

Übersicht über die Interaktion zwischen WPF und Win32

Threading-Modell

Übersicht über die Eingabe

Referenz

ComponentDispatcher

IKeyboardInputSink