so, I've been developing a class to handle Kwyboard input in a VSTO add-in, so far I've been using Windows hooks to do so with relative success.
Having this code:
//.....
private const int WH_KEYBOARD = 2;
private const int WH_MOUSE = 7;
private enum WM : uint {
KEYDOWN = 0x0100,
KEYFIRST = 0x0100,
KEYLAST = 0x0108,
KEYUP = 0x0101,
MOUSELEFTDBLCLICK = 0x0203,
MOUSELEFTBTNDOWN = 0x0201,
MOUSELEFTBTNUP = 0x0202,
MOUSEMIDDBLCLICK = 0x0209,
MOUSEMIDBTNDOWN = 0x0207,
MOUSEMIDBTNUP = 0x0208,
MOUSERIGHTDBLCLK = 0x0206,
MOUSERIGHTBTNDOWN = 0x0204,
MOUSERIGHTBTNUP = 0x0205
}
private hookProcedure proc;
private static IntPtr hookID = IntPtr.Zero;
//Enganches
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr SetWindowsHookEx(int hookId, hookProcedure proc, IntPtr hInstance, uint thread);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool unHookWindowsHookEx(int hookId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr CallNextHookEx(IntPtr hookId, int ncode, IntPtr wparam, IntPtr lparam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string name);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetCurrentThreadId();
public CPInputListener() {
proc = keyBoardCallback;
hookID = setHook(proc);
}
private IntPtr setHook(hookProcedure procedure){
ProcessModule module = Process.GetCurrentProcess().MainModule;
uint threadId = (uint)GetCurrentThreadId();
return SetWindowsHookEx(WH_KEYBOARD, procedure, IntPtr.Zero, threadId);
}
public void stopListeningAll() {
unHookWindowsHookEx(WH_KEYBOARD);//For now
}
private IntPtr keyBoardCallback(int ncode, IntPtr wParam, IntPtr lParam) {
if (ncode >= 0) {
//LPARAM pretty useless
Keys key = (Keys)wParam;
KeyEventArgs args = new KeyEventArgs(key);
onKeyDown(args);//for now
}
return CallNextHookEx(hookID, ncode, wParam, lParam);
}
//....
I do successfully receive keyboard input, but here is the big mistery; each time a key is pressed, no matter how fast it was, the event (onKeyDown) is called 10 times exactly, no more no less.
If the key is long pressed, the event keep being called but 10 by 10 times instead of calling just once.
So far I've tried
- Using wParam to call the required event on Key Up: Doesn't seem to work, in all codes I've seen dealing with Key down and up events,
IntPtr wParam
is used, but from that variable I can only retrieve the keycode which doesn't help. - Using
lParam
ornCode
: These vars are giving unconsistent values between those 10 calls,ncode
tends to retrieve 0's and 3's andlParam
some values which seem to be unmanaged memory adresses...
What do I expect
I do expect for onKeyDown to be called just once when the key is pressed or in the other hand being able to call the method by on key up which i do expect to be called just once per key releasing.
How to bypass this
If I can't find a reasonable answer, I was thinking on using a custom made timer to discard all those callings and use only the last one, would you recommend this if everything else fails?
Thanks a lot! Be happy and be kind! :D