Hi,
I'm implementing a hotkey tool that globally captures key press/release and sends out keyboard events when receiving a defined key combination.
I started implementing a global system hook that generates keyboard press/release events. Some Code snippets:
// installs an application-defined hook procedure into a hook chain //
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int SetWindowsHookEx(
int idHook,
HookProc lpfn,
IntPtr hMod,
int dwThreadId);
// passes the hook information to the next hook procedure in the current hook chain //
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(
int idHook,
int nCode,
int wParam,
IntPtr lParam);
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/callwndproc.asp //
// Create an instance of HookProc.
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
//install hook
hKeyboardHook = SetWindowsHookEx(
WH_KEYBOARD_LL,
KeyboardHookProcedure,
Marshal.GetHINSTANCE(
Assembly.GetExecutingAssembly().GetModules()[0]),
0);
// I now am able to capture key up/press/down events //
public event KeyEventHandler KeyDown;
public event KeyPressEventHandler KeyPress;
public event KeyEventHandler KeyUp;
//read structure KeyboardHookStruct at lParam
KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
//raise KeyDown
if (KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
KeyEventArgs e = new KeyEventArgs(keyData);
KeyDown(this, e);
handled = handled || e.Handled;
}
Within the main app I added the event handlers (actHook is the class which created/handles the above mentioned hook chain)
actHook.KeyDown += new KeyEventHandler(MyKeyDown);
actHook.KeyUp += new KeyEventHandler(MyKeyUp);
I'm now listening to global key events and start doing stuff if one key combination is been triggered (here CTRL+D):
private bool working = false;
public void MyKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.LControlKey) isCtrlDown = true;
if (e.KeyData == Keys.D) isDDown = true;
if (!working) CheckHotkey();
else
{
e.SuppressKeyPress = true;
}
}
private void CheckHotkey()
{
// STRG + D //
if (isCtrlDown && isDDown)
{
working = true;
DoStrgD();
working = false;
}
}
private void DoStrgD()
{
SendKeys.SendWait("{LEFT}");
SendKeys.Flush();
}
An here is the problem. The code does what is should. When pressing CTRL+D, the DoStrgD() function is been called which sends out a Key event "LEFT". The strange thing is, the first time the function is been called, the SendKeys command is sending a single "LEFT" - the next time, a CTRL Key is also been send, resulting in a CTRL+LEFT command. It seems, that the CTRL key (beeing catched by the keyhook) still is in cache, being transmitted when calling SendKeys.
Is there any way to supress the CTRL Key beeing send by SendKeys?
Why is it working the first time, the function DoStrgD() is been called?
Any idea, comments?
Regards, Andi.