Rubrik: Maus & Tastatur · Tastatursteuerung | VB-Versionen: VB2005, VB2008 | 30.03.09 |
Tastatureingaben VOR Windows abfangen Mithilfe eines globalen Hooks können die Tastendrücke vor Windows abgefangen werden. | ||
Autor: Florian Kolb | Bewertung: | Views: 27.765 |
www.fk-freeware.de.vu | System: Win2k, WinXP, Win7, Win8, Win10, Win11 | Beispielprojekt auf CD |
Gibt es eigentlich eine Möglichkeit, die Tastendrücke bereits VOR dem Betriebssystem abzufangen? Die gibt es. Mit einem globalen Hook ist das möglich. Dieser fängt in einer Funktion die Tastatureingaben ab und legt fest, ob und welche Eingaben z. B. auch verworfen werden können! Denn damit hat das Ereignis für Windows nie stattgefunden.
Doch wie geht das jetzt? Dafür wird die Funktion "SetWindowsHookExW" aus der user32.dll benötigt. Für das Löschen des Hooks verwenden wir "UnhookWindowsHookEx". Damit die Tastatureingaben aber noch abgefangen werden können, muss die Funktion "KeyboardHookProc" her.
Das ganze sieht dann wie folgt aus:
Imports System.Runtime.InteropServices Public Class Form1
Private Declare Sub keybd_event Lib "user32" ( _ ByVal bVk As Byte, _ ByVal bScan As Byte, _ ByVal dwFlags As Integer, _ ByVal dwExtraInfo As Integer) Private Const KEYEVENTF_KEYUP = &H2 Private Delegate Function HOOKPROCDelegate( _ ByVal nCode As Integer, _ ByVal wParam As IntPtr, _ ByRef lParam As KBDLLHOOKSTRUCT) As IntPtr ' dauerhafte Delegaten-Variable erzeugen Private HookProc As New HOOKPROCDelegate(AddressOf KeyboardHookProc) Private Declare Unicode Function GetModuleHandleW Lib "kernel32.dll" ( _ ByVal lpModuleName As IntPtr) As IntPtr ' Die Funktion, um einen globalen Hook setzen zu können: Private Declare Unicode Function SetWindowsHookExW Lib "user32.dll" ( _ ByVal idHook As Integer, _ ByVal lpfn As HOOKPROCDelegate, _ ByVal hMod As IntPtr, _ ByVal dwThreadId As UInteger) As IntPtr ' Für das Löschen des Hooks wird diese Funktion verwendet: Private Declare Unicode Function UnhookWindowsHookEx Lib "user32.dll" ( _ ByVal hhk As IntPtr) As UInteger Private Declare Unicode Function CallNextHookEx Lib "user32.dll" ( _ ByVal hhk As IntPtr, _ ByVal nCode As Integer, _ ByVal wParam As IntPtr, _ ByRef lParam As KBDLLHOOKSTRUCT) As IntPtr Private Const WM_KEYDOWN As Int32 = &H100 ' Konstante für WM_KEYDOWN Private Const WM_KEYUP As Int32 = &H101 ' Konstante für WM_KEYUP Private Const HC_ACTION As Integer = 0 ' Konstante für HC_ACTION Private Const WH_KEYBOARD_LL As Integer = 13 ' Konstante für WH_KEYBOARD_LL Public PrevWndProc As Integer Private mHandle As IntPtr <StructLayout(LayoutKind.Sequential)> Public Structure KBDLLHOOKSTRUCT Public vkCode As Keys Public scanCode, flags, time, dwExtraInfo As UInteger Public Sub New(ByVal key As Keys, _ ByVal scancod As UInteger, _ ByVal flagss As UInteger, _ ByVal zeit As UInteger, _ ByVal extra As UInteger) vkCode = key scanCode = scancod flags = flagss time = zeit dwExtraInfo = extra End Sub End Structure
' Um den Hook ein-/ausschalten zu können: Public Property KeyHookEnable() As Boolean Get Return mHandle <> IntPtr.Zero End Get Set(ByVal value As Boolean) If KeyHookEnable = value Then Return If value Then mHandle = SetWindowsHookExW(WH_KEYBOARD_LL, HookProc, _ GetModuleHandleW(IntPtr.Zero), 0) Else UnhookWindowsHookEx(mHandle) mHandle = IntPtr.Zero End If End Set End Property
' Hiermit wird der Tastendruck VOR dem Betriebssystem abgefangen: ' wParam kann folgende Werte annehmen: ' WM_KEYUP und WM_KEYDOWN (Taste gedrückt/losgelassen) ' wird fEatKeyStroke=true gesetzt, so wird dieser Tastendruck "verschluckt", ' d. h. er hat für das System NIE statt gefunden. Private Function KeyboardHookProc(ByVal nCode As Integer, _ ByVal wParam As IntPtr, _ ByRef lParam As KBDLLHOOKSTRUCT) As IntPtr Dim fEatKeyStroke As Boolean If nCode = HC_ACTION Then Select Case lParam.vkCode ' Hier z.B. die Zeichen a und b nicht zulassen '(fEatKeyStroke = True) Case Keys.A fEatKeyStroke = True Case Keys.B fEatKeyStroke = True End Select If fEatKeyStroke Then Return New IntPtr(1) Exit Function End If Return CallNextHookEx(mHandle, nCode, wParam, lParam) End If End Function
Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Hook einschalten: KeyHookEnable = True End Sub
Private Sub Form1_Closing(ByVal sender As System.Object, _ ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing ' WICHTIG! Hook ausschalten beim Beenden nicht vergessen!!! KeyHookEnable = False End Sub
End Class