2009-02-08 2 views
5

Ich versuche, eine Anwendung zu schreiben, die reagiert, wann immer die Umschalttaste gedrückt wird, egal welche Anwendung gerade Fokus hat.Reagieren Sie auf die Tastatur, wenn Sie nicht im Fokus sind? (C#, Vista)

Ich versuchte dies mit SetWindowsHookEx() und mit GetKeyboardState(), aber beide funktionieren nur, wenn das Fenster der Anwendung den Fokus hat. Ich brauche es, um global zu arbeiten.

Wie mache ich das?

Antwort

5

Keine der angegebenen Antworten hat mir geholfen, mein Problem zu lösen, aber ich habe die Antwort selbst gefunden. Hier ist es.

Mit SetWindowsHookEx() mit WH_KEYBOARD_LL war der richtige Ansatz. Allerdings sind die anderen Parameter zu SetWindowsHookEx() unintuitive:

  • Der letzte Parameter, dwThreadId muss 0.
  • Der zweitletzte Parameter, hMod, bis zu einem gewissen DLL-zu-Punkt sein muss. Ich verwendete User32, die eine DLL ist, die sowieso immer geladen wird und von allen Prozessen mit einer GUI verwendet wird. Ich habe diese Idee von a CodeProject post about this.

So sieht der Code ein bisschen wie folgt aus:

instance = LoadLibrary("User32"); 
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookFunction, instance, 0); 

Die Dokumentation ist unklar, über die zweitletzte Parameter. Es heißt:

Der hMod-Parameter muss auf NULL gesetzt werden, [...] wenn die Hook-Prozedur innerhalb des Codes ist, der dem aktuellen Prozess zugeordnet ist.

Es gibt nicht an, dass dies auf einige Arten von Haken gilt nur, aber nicht beschränkt auf WH_KEYBOARD_LL und WH_MOUSE_LL.

+0

Ja, es ist was sie bedeuten - für eine Low-Level-Maus oder Tastatur-Hook (oder einen anderen lokalen Hook) sollte HMod IntPtr.Zero sein. –

+0

Hmmm, du sagst, dass die anderen Beiträge nicht hilfreich waren, fahre fort, die gleiche Antwort zu posten, die nobugz bereits angegeben hat, und markiere deine als die richtige Antwort. –

+0

Nobugz sagt überhaupt nichts über hMod, und im Gegensatz zu Ihrem ersten Kommentar schlägt diese Antwort vor, dass hMod auf etwas ** anderes ** als IntPtr.Zero gesetzt wird. –

5

Sie werden SetWindowsHookEx (verwenden). Es gibt nur zwei Arten von Hooks, die Sie in einer verwalteten Sprache implementieren können: WH_KEYBOARD_LL und WH_MOUSE_LL. Alle anderen Hooks benötigen eine DLL, die in einen anderen Prozess eingefügt werden kann. Verwaltete DLLs können nicht injiziert werden, die CLR kann nicht initialisiert werden.

Diese blog post hat ein funktionelles Beispiel.

+0

Die meisten anderen Hooks können auch in einer verwalteten Sprache implementiert werden, aber nur, wenn sie auf Threads des aktuellen Prozesses beschränkt sind. Low-Level-Maus- und Tastatur-Hooks sind die einzigen 'globalen' Hooks, die erlaubt sind. –

+0

Dies streift nur die Oberfläche des Problems und geht nicht wirklich in eine Tiefe. –

+1

Dies ist eine sehr spezifische Antwort auf die spezifische Frage. Es ist ein bisschen kurz und beschönigt einige Informationen zur Vereinfachung, aber es enthält alle Informationen, die ein kompetenter Softwareentwickler benötigen würde. –

2

Wenn Sie die Technik in der von nobugz referenzierten Post verwenden, müssen Sie sicherstellen, dass der Delegat keine Müllsammlung erhält, z. indem Sie GC.KeepAlive (_proc) verwenden, wenn Sie den Hook setzen, andernfalls wird der Hook nach einer unbestimmten Zeit nicht mehr funktionieren, wenn der Delagate deaktiviert wird.

Verwandte Themen