keyhook legt sondertasten lahm
-
hallo
ich habe mir einen code zum auffangen von tastenanschlägen und mausklicks gebastelt. fängt soweit auch alles auf, nur funktionieren die sondertasten von meiner ms multimedia tastatur nicht mehr wenn der hook aktiv ist. hat hier jemand eine idee??gruss peter h
mein code:
using System; using System.Diagnostics; using System.Runtime.InteropServices; public class UniversalHook : IDisposable { //Variables used in the call to SetWindowsHookEx protected HookHandlerDelegate proc; protected IntPtr hookID = IntPtr.Zero; protected delegate IntPtr HookHandlerDelegate(int nCode, IntPtr wParam, ref IntPtr lParam); #region DllImports [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] protected static extern IntPtr SetWindowsHookEx(int idHook, HookHandlerDelegate lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] protected static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] protected static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] protected static extern IntPtr GetModuleHandle(string lpModuleName); #endregion // Constructor: set up a hook public UniversalHook() { } // Release the hook public void Dispose() { UnhookWindowsHookEx(hookID); } // Processes the event captured by the hook protected virtual IntPtr HookCallback(int nCode, IntPtr wParam, ref IntPtr lParam) { return (System.IntPtr)1; } #region Event stuff // Delegate for Hook event handling public delegate void HookEventHandler(HookEventArgs e); // Event triggered when a keystroke is intercepted by the low-level hook public event HookEventHandler KeyIntercepted; // Raises the KeyIntercepted event. public void OnKeyIntercepted(HookEventArgs e) { if (KeyIntercepted != null) KeyIntercepted(e); } // Event arguments for the KeyIntercepted event public class HookEventArgs : EventArgs { private int iKeyCode; public HookEventArgs(int VK_KeyCode) { iKeyCode = VK_KeyCode; } public int KeyCode { get { return iKeyCode; } } } #endregion } public class KeyboardHook : UniversalHook { //API constants private const int WH_KEYBOARD_LL = 13; private const int WM_KEYUP = 0x0101; private const int WM_SYSKEYUP = 0x0105; // Constructor: set up a keyboard hook to trap all keystrokes public KeyboardHook() { proc = new HookHandlerDelegate(HookCallback); using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { hookID = SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } // Processes the key event captured by the hook protected override IntPtr HookCallback(int nCode, IntPtr wParam, ref IntPtr lParam) { //Filter wParam for KeyUp events only if (nCode >= 0 && (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)) OnKeyIntercepted(new HookEventArgs((int)lParam)); //Pass key to next application return CallNextHookEx(hookID, nCode, wParam, lParam); } } public class MouseHook : UniversalHook { // API constants private const int WH_MOUSE_LL = 14; private const int WM_LBUTTONDOWN = 0x0201; private const int WM_RBUTTONDOWN = 0x0204; // Constructor: set up a mouse hook public MouseHook() { proc = new HookHandlerDelegate(HookCallback); using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { hookID = SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } // Processes the key event captured by the hook protected override IntPtr HookCallback(int nCode, IntPtr wParam, ref IntPtr lParam) { //Filter wParam for KeyUp events only if (nCode >= 0 && wParam == (IntPtr)WM_LBUTTONDOWN) OnKeyIntercepted(new HookEventArgs(1)); else if (nCode >= 0 && wParam == (IntPtr)WM_RBUTTONDOWN) OnKeyIntercepted(new HookEventArgs(2)); //Pass key to next application return CallNextHookEx(hookID, nCode, wParam, lParam); } }
-
Eventuell solltest du die Tastenereignisse, die du nicht selber verarbeiten willst, an dein System zurückgeben - dann hat es die Chance, sie an andere interessierte Programm weiterzuleiten.
(unter WinAPI C++ verwendet man afaik die CallNextHookEx(), wie die entsprechende C# Funktion heißt, weiß ich nicht)
-
Hallo!
Die Funktion CallNextHookEx wird am Ende der Funktion HookCallback aufgerufen. Die Standarttasten funktionieren ja problemlos, nur z.B. die Multimediatasten und Hotkeys arbeiten nicht mehr.
Gruss Peter H
-
Hast du das Programm mal durch den Debugger laufen lassen?
-
Ja, habe schon versucht mit dem Debugger etwas zu erkennen, aber weis nicht genau worauf ich achten soll. CallNextHookEx() wird jedenfall immer korrekt aufgerufen.
-
Problem gelöst...
Es hat nicht gereicht einfach lParam weiterzuleiten, sondern man muss die KBDLLHOOKSTRUCT verwenden die der Hook zurückgiebt. Hat irgendwie etwas mit dem ScanCode bei den Sondertasten zu tun.Hier der bereinigte Code. Vielleicht hilfts mal jemandem:
using System; using System.Diagnostics; using System.Runtime.InteropServices; public class UniversalHook : IDisposable { //Variables used in the call to SetWindowsHookEx protected HookHandlerDelegate proc; protected IntPtr hookID = IntPtr.Zero; protected delegate IntPtr HookHandlerDelegate(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam); // Structure returned by the hook protected struct KBDLLHOOKSTRUCT { public int vkCode; int scanCode; public int flags; int time; int dwExtraInfo; } #region DllImports [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] protected static extern IntPtr SetWindowsHookEx(int idHook, HookHandlerDelegate lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] protected static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] protected static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] protected static extern IntPtr GetModuleHandle(string lpModuleName); #endregion public UniversalHook() { // set up desired hook using SetWindowsHookEx } // Release the hook public void Dispose() { UnhookWindowsHookEx(hookID); } // Processes the event captured by the hook protected virtual IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam) { return (System.IntPtr)1; } #region Event stuff // Delegate for Hook event handling public delegate void HookEventHandler(HookEventArgs e); // Event triggered when a keystroke is intercepted by the low-level hook public event HookEventHandler KeyIntercepted; // Raises the KeyIntercepted event. public void OnKeyIntercepted(HookEventArgs e) { if (KeyIntercepted != null) KeyIntercepted(e); } // Event arguments for the KeyIntercepted event public class HookEventArgs : EventArgs { private int iKeyCode; public HookEventArgs(int VK_KeyCode) { iKeyCode = VK_KeyCode; } public int KeyCode { get { return iKeyCode; } } } #endregion } public class KeyboardHook : UniversalHook { //API constants private const int WH_KEYBOARD_LL = 13; private const int WM_KEYUP = 0x0101; private const int WM_SYSKEYUP = 0x0105; // Constructor: set up a keyboard hook to trap all keystrokes public KeyboardHook() { proc = new HookHandlerDelegate(HookCallback); using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { hookID = SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } // Processes the key event captured by the hook protected override IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam) { //Filter wParam for KeyUp events only if (nCode >= 0 && (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)) OnKeyIntercepted(new HookEventArgs(lParam.vkCode)); //Pass key to next application return CallNextHookEx(hookID, nCode, wParam, ref lParam); } } public class MouseHook : UniversalHook { // API constants private const int WH_MOUSE_LL = 14; private const int WM_LBUTTONDOWN = 0x0201; private const int WM_RBUTTONDOWN = 0x0204; // Constructor: set up a mouse hook public MouseHook() { proc = new HookHandlerDelegate(HookCallback); using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { hookID = SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } // Processes the key event captured by the hook protected override IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam) { //Filter wParam for KeyUp events only if (nCode >= 0 && wParam == (IntPtr)WM_LBUTTONDOWN) OnKeyIntercepted(new HookEventArgs(lParam.vkCode)); else if (nCode >= 0 && wParam == (IntPtr)WM_RBUTTONDOWN) OnKeyIntercepted(new HookEventArgs(lParam.vkCode)); //Pass key to next application return CallNextHookEx(hookID, nCode, wParam, ref lParam); } }
-
Hallo,
Hmm... vllt. hilfts ja klingt gut
hatte auch vor, so ein Programm zu schreiben, und da bin ich hier auf deinen Code aufmerksam geworden.
Nun hab ich mir den Code mal angesehen und finde ihn recht interessant. Aber wo schreibt man denn deinen Code rein, damit es funktioniert?
Und muss man noch irgendwelche Libs, DLLs, sonstiges includen?Hoffe auf eine schnelle Antwort.
Danke schonmal.
Gruß
MWJK
-
Seit ihr nicht irgendwie im falschen Subforum :xmas2: ?!
-
hallo
habe die antwort erst heute entdeckt.
dlls, libs muss man keine mehr hinzufügen. ist im code schon geschehen.diese anleitung funktioniert so unter visual studio 2005:
den kompletten code in eine datei kopieren und deinem projekt hinzufügen
um den hook zu verwenden musst du eine neue objekt instanz erzeugen. das habe ich in der Program.cs die von vs erstellt wird gemacht:... public static KeyboardHook kh; public static MouseHook mh; static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); using (kh = new KeyboardHook()) using (mh = new MouseHook()) { Application.Run(new FormMain()); } } ...
ab sofort wird bei jedem tastendruck ein event gefeuert, dass man verarbeiten kannpublic partial class FormMain : Form { public FormMain() { InitializeComponent(); Program.kh.KeyIntercepted += new UniversalHook.HookEventHandler(OnKeyInterceptedHandler); Program.mh.KeyIntercepted += new UniversalHook.HookEventHandler(OnKeyInterceptedHandler); } void OnKeyInterceptedHandler(UniversalHook.HookEventArgs e) { dataGridViewEvents.Rows.Add(new object[] { e.vkCode, e.scanCode, e.flags, e.time, e.dwExtraInfo }); } ... }hoffe die erklärung ist ausreichend. tut mir leid wenn das evtl. im falschen forum steht, aber die frage war ursprünglich zur winapi.
gruss peter_h
-
Thx für die erklärung.
Tut mir auch leid, sollte ich diese Frage im falschen Forum gestellt haben, aber der Thread war leider hier schon eröffnet und deshalb hatte ich meine Frage angehangen.
Gruß
MWJK