Hooking the keyboard message queue in compact framework code
Print This Post
Here is some nice code to use a keyboard hook implemented in C# for compact framework.
You can use this to catch the funny OS asigned keys like F1, F2, F3, F4, F6 and F7 (Softkey 1 and 2, Phone, End, Volume Up, Volume Down); and last but not least catch the Win Key press.
The hooking class:
using System;
using System.Runtime.InteropServices;
/*
In order to use this class in your program, just declare the varialble and hook up into HookEvent:
HookKeys hook = new HookKeys();
hook.HookEvent += new HookKeys.HookEventHandler(HookEvent);
hook.Start();
*/
public class HookKeys
{
#region delegates
public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
public delegate void HookEventHandler(HookEventArgs e, KeyBoardInfo keyBoardInfo);
public HookEventHandler HookEvent;
#endregion
#region fields
private HookProc hookDeleg;
private static int hHook = 0;
#endregion
public HookKeys()
{
}
~HookKeys(){
if(hHook!=0)
this.Stop();
}
#region public methods
///
/// Starts the hook
///
public void Start()
{
if (hHook != 0)
{
//Unhook the previouse one
this.Stop();
}
hookDeleg = new HookProc(HookProcedure);
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, hookDeleg, GetModuleHandle(null), 0);
if (hHook == 0)
{
throw new SystemException("Failed acquiring of the hook.");
}
AllKeys(true);
}
///
/// Stops the hook
///
public void Stop()
{
UnhookWindowsHookEx(hHook);
AllKeys(false);
}
#endregion
#region protected and private methods
protected virtual void OnHookEvent(HookEventArgs hookArgs, KeyBoardInfo keyBoardInfo)
{
if (HookEvent != null)
{
HookEvent(hookArgs, keyBoardInfo);
}
}
private int HookProcedure(int code, IntPtr wParam, IntPtr lParam)
{
KBDLLHOOKSTRUCT hookStruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
if (code < 0)
return CallNextHookEx(hookDeleg, code, wParam, lParam);
// Let clients determine what to do
HookEventArgs e = new HookEventArgs();
e.Code = code;
e.wParam = wParam;
e.lParam = lParam;
KeyBoardInfo keyInfo = new KeyBoardInfo();
keyInfo.vkCode = hookStruct.vkCode;
keyInfo.scanCode = hookStruct.scanCode;
OnHookEvent(e, keyInfo);
// Yield to the next hook in the chain
return CallNextHookEx(hookDeleg, code, wParam, lParam);
}
#endregion
#region P/Invoke declarations
[DllImport("coredll.dll")]
private static extern int AllKeys(bool bEnable);
[DllImport("coredll.dll")]
private static extern int SetWindowsHookEx(int type, HookProc hookProc, IntPtr hInstance, int m);
[DllImport("coredll.dll")]
private static extern IntPtr GetModuleHandle(string mod);
[DllImport("coredll.dll")]
private static extern int CallNextHookEx(
HookProc hhk,
int nCode,
IntPtr wParam,
IntPtr lParam
);
[DllImport("coredll.dll")]
private static extern int GetCurrentThreadId();
[DllImport("coredll.dll", SetLastError = true)]
private static extern int UnhookWindowsHookEx(int idHook);
private struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public IntPtr dwExtraInfo;
}
const int WH_KEYBOARD_LL = 20;
#endregion
}
#region event arguments
public class HookEventArgs : EventArgs
{
public int Code; // Hook code
public IntPtr wParam; // WPARAM argument
public IntPtr lParam; // LPARAM argument
}
public class KeyBoardInfo
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
}
#endregion
Here is the download of the Visual Studio 2005 Windows Mobile 6 SDK targeting source code:
DOWNLOAD:KbdHookCS - Keyboard hooking in compact framework (Hits: 1025, size: 31.69 KB)







Thanks, this little Class saved my day!
Thanks allot,
The behavior is not consistent, some times one press on keyboard is being interpreted as two clicks, do you know what could be the reason?
Adi
???-)
The hook code simply enables you to see keyboard messages. You have to look for WM_KEYDOWN and/or WM_KEYUP yourself in the hookeventhandler. Every keypress on the hardware keyboard may produce two and more messages depending on the key pressed. If you press the(a) key and CAPS lock is on, you will get wm_keydown+shift; wm_keydown+’a';(wm_char(‘A’);wm_keyup+’a';wm_keyup+shift
Sorry, but without any code I cant say what you are doing wrong.
regards
Josef