Hooking the keyboard message queue in compact framework code
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 not found]Update 20. sept 2019:
Better code which will start/stop the hook with Activate/Deactivate (Show/Minimize) of a form:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace HookCEtest
{
public partial class Form1 : Form
{
HookKeys hook;
public Form1()
{
InitializeComponent();
// Inizialize keyboard hook event handler. Calls "HookEvent" method,
// when any hardware button is pressed on the field computer.
hook = new HookKeys();
hook.HookEvent += new HookKeys.HookEventHandler(HookEvent);
//hook.Start();
}
private void HookEvent(HookEventArgs e, KeyBoardInfo keyBoardInfo)
{
/*
This method is called, when any hardware button is pressed.
When a defined button is pressed, foreground windows toggles background
color.
*/
System.Diagnostics.Debug.WriteLine(String.Format("HookEvent called: vkCode={0}", keyBoardInfo.vkCode));
if (keyBoardInfo.vkCode == 123 && e.wParam.ToInt32() == 256) // Home button pressed
{
System.Diagnostics.Debug.WriteLine("Search button pressed");
ToggleWindow();
}
}
private void ToggleWindow()
{
// Bring window of other software to front
Color old = this.BackColor;
this.BackColor = Color.Blue;
this.Refresh();
System.Threading.Thread.Sleep(1000);
this.BackColor = old;
}
private void Form1_Activated(object sender, EventArgs e)
{
hook.Start();
}
private void Form1_Deactivate(object sender, EventArgs e)
{
hook.Stop();
}
}
}
If you do not use the above, a system thread is stopped when Form is minimized:
'HookCEtest.exe' (Managed): Loaded 'C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v3.5\Debugger\BCL\System.Drawing.dll' HookEvent called: vkCode=123 HookEvent called: vkCode=123 HookEvent called: vkCode=118 HookEvent called: vkCode=118 HookEvent called: vkCode=123 HookEvent called: vkCode=123 The thread 0xe9ad0012 has exited with code 0 (0x0).
The HookKeys itself does not use any custom thread!



http://www.led-mg.de