2009-09-03 6 views
6

Ich habe daran gearbeitet, Eingaben in eine WPF-Anwendung zu injizieren. Was dieses Projekt schwierig macht, ist, dass ich in der Lage sein muss, die Eingabe in die Anwendung zu injizieren, obwohl sie im Hintergrund läuft (d. H. Eine andere Anwendung hat den Eingabefokus). Die Verwendung der SendInput() Funktion ist daher nicht in Frage.Mauseingabe in WPF-Anwendungen injizieren

Bis jetzt habe ich Tastatureingabe funktioniert, aber habe Probleme beim injizieren Mauseingabe.

Ich verwendete Spy ++, um die Fenstermeldungen zu beobachten, die an das WPF-Fenster gesendet werden, wenn ich die Maustaste physikalisch klicke. Ich fertige dann einfach dieselben Mausnachrichten (z. B. WM_LBUTTONDOWN und WM_LBUTTONUP) manuell an und sende sie explizit an das WPF-Fenster, um die Mauseingabe zu emulieren.

Leider funktioniert das nicht wie erwartet (nicht einmal wenn ich zu Testzwecken das WPF-Fenster als Vordergrundfenster eingestellt habe).

Ich habe eine Schaltfläche zu meinem WPF-Testfenster hinzugefügt, die nach dem Anklicken ein Meldungsfeld anzeigt. Das Einfügen der entsprechenden Mausnachrichten, wenn ich den Cursor manuell über die Schaltfläche positioniert habe, bewirkt jedoch nicht, dass auf die Schaltfläche geklickt wird (d. H. Das angeklickte Ereignis wird nicht vom WPF-Framework ausgelöst).

Wenn ich einen Handler für Mausklicks auf dem tatsächlichen Dialog (der Client-Bereich) hinzufügen, dass Handler tut aufgerufen, wenn ich den Cursor über den Dialog selbst positionieren und injizieren die gleichen Fenstermeldungen wie zuvor:

Seltsamerweise, wenn ich den Push-Modus der Schaltfläche zu drücken (dh es gilt als Klick auf die Maus nach unten anstatt die Standard-Maus nach oben), die Taste angeklickt Ereignis ausgelöst wird, wenn ich die gleichen Nachrichten wie zuvor injizieren. (Es ist erwähnenswert, dass der Handler aus dem obigen Beispiel korrekt für beide Maus-Downs und Ups abfeuert, so scheint es, dass das WPF-Framework beide Nachrichten erfolgreich verarbeitet.)

Es scheint, als gäbe es einige andere Kriterien, die müssen erfüllt sein, damit ein angeklicktes Mausereignis vom WPF-Framework ausgelöst wird. Weiß jemand, wie die Mauseingabe intern in WPF gehandhabt wird, oder warum sie meine Maus-Auf- und -Abmeldungen nicht als Klick auf die Schaltfläche interpretiert?

(Es ist erwähnenswert, dass dieser Ansatz [sending window messages] funktioniert gut auf gewöhnlichen Win32-Windows, wie der Start -> Ausführen-Dialog. Der Unterschied hier ist, dass WPF hat nur ein physisches Win32-Fenster und der Rest ist WPF spezifisch , was bedeutet, dass alle Fenstermeldungen zu diesem Fenster der obersten Ebene anstatt der eigentlichen Schaltfläche gehen.)

Ich habe High und Low für eine Antwort zu diesem Thema gesucht und würde beliebige Gedanken oder Ideen schätzen.

+0

Je nach Anforderung kann es sich lohnen, die Benutzeroberflächenautomatisierung zu betrachten, anstatt zu versuchen, Eingaben zu simulieren. Aber das hängt sehr stark davon ab, was Sie versuchen, Input * für * zu injizieren - es ist eher ein Steuerelement-Level-Zeug als ein Pixel-Level-Zeug ... – itowlson

+0

Ja, und es gibt verschiedene Ebenen der UI-Automatisierung: http : //blogs.msdn.com/ivo_manolov/archive/2008/12/15/9223397.aspx Ich habe bereits in TestAPI untersucht, um die Eingabe zu injizieren/zu automatisieren, aber unglücklicherweise verwenden sie SendInput() eher unter der Haube als einfach die Eingabe direkt in den WPF-Rahmen zu injizieren. – dreijer

+0

Entschuldigung für Nekroskopie, aber jetzt mit der Referenzquelle von .NET zur Verfügung, kann dies tiefer geschaut werden https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/Primitives/ButtonBase.cs , 414 –

Antwort

1

Verwenden UI-Automatisierung, um dies zu tun - versuchen, Eingabe über Fenstermeldungen manuell zu simulieren, ist ein Lehrbuchfehler, wie der Versuch, einen Landkrieg gegen Russland zu starten.

+0

Wie ich in meinem vorherigen Kommentar gesagt habe, wird das aus mehreren Gründen nicht wirklich funktionieren. Verwenden von z.B. Das TestAPI-Framework zum Simulieren von Mausklicks wird unter der Haube in SendInput() übersetzt. Gehen Sie einen anderen Weg der Identifizierung, welches Steuerelement unter dem Cursor ist und dann das Steuerelement explizit aufrufen, hat seine eigenen Probleme aufgrund der Steuermuster, die für die Steuerelemente variieren: http://social.msdn.microsoft.com/Forums/en -US/windowsaccessibilityandautomation/thread/25972b31-ac1a-401e-aab3-b7c8b1b96694 # a776adcb-e6d2-43fa-b78c-da6de7628d4e – dreijer

0

Ihre Strategie ist grundsätzlich solide, aber um eine Nachricht an ein Fenster zu senden, das einem anderen Prozess gehört, müssen Sie zuerst die Nachricht registrieren.

Here is an article explaining the whole business. Der Beispielcode ist leider in VB, aber ich bin mir sicher, dass dich das nicht aufhalten wird.

+0

Danke für die Eingabe (Entschuldigung das Wortspiel :). Ich injiziere die Nachrichten innerhalb desselben Prozesses auf demselben GUI-Thread. Es gibt also keine Berechtigungsprobleme. Wie ich in meiner ersten Frage geschrieben habe, werden die Nachrichten manchmal vom WPF-Framework korrekt verarbeitet (wie beim Klicken auf den Dialog selbst). – dreijer

+0

Ja, ich habe gerade den Teil Ihrer Frage bemerkt, in dem Sie erwähnen, dass Sie einige Mausereignisse auslösen, was bedeutet, dass alles inproc ist. –

3

Ich würde sehr empfehlen, die UIAutomation Route zu gehen. Sie erstellen ein AutomationElement nach Fensterhandle. Crawlen Sie zum Button und rufen Sie ihn auf. Ich möchte nur wissen, wie Sie es geschafft haben, dass die Tastatureingabe funktioniert. Ich versuche derzeit, das umgekehrte Problem zu lösen. Wie bekomme ich ein WPF-Fenster (ich habe es über Win32-Aufrufe erreicht), um auf virtuelle Tastaturmeldungen zu reagieren. Ich habe ++ Spionagesitzungen auf dem fraglichen Fenster angemeldet und seine Eingabe ohne Erfolg repliziert.

+0

Das Problem dabei ist, dass ich nicht unbedingt weiß, auf was (Art der Kontrolle) der Benutzer klickt. Wie könnte es eine Schaltfläche sein, könnte es eine Bildlaufleiste sein, könnte es die Web-Browser-Steuerelement sein. Es fällt mir schwer zu visualisieren, wie all diese Steuerelemente unterstützt werden, ohne jeden einzelnen Typ zu umschließen. Stellen Sie für die Tastatureingabe sicher, dass Sie die Nachrichten veröffentlichen, die gepostet werden sollen (z. B. PostMessage() oder SendMessage()). Sie können auch versuchen, während der Ausführung im Kontext des GUI-Threads zu posten. – dreijer