天天看點

Windows Mobile/Windows CE開發技巧 —— 使用鈎子實作自定義系統功能鍵

在自己開發的程式裡,實作自定義功能鍵,是比較容易的事。但是,如果需要實作一些系統級别的按鍵自定義,在離開自己開發程式界面,或者在其他程式的界面,可以響應到按鍵事件,隻能使用鈎子的方式實作。

請參考以下例子,例子中捕獲了Code=112,113,114,115,116鍵值的按鍵(一般代表一些PDA的F1,F2,F3,F4,F5鍵):

class HookKeyClass
{
	public delegate int HookKeyProc(int code, IntPtr wParam, IntPtr lParam);
	public delegate void KeyEventHandler(int KeyValue);
	public event KeyEventHandler KeyEvent;
	private HookKeyProc hookKeyDeleg;
	private int hHookKey = 0;
	public HookKeyClass()
	{ Start(); }
	~HookKeyClass()
	{ Stop(); }

	#region public methods
	//安裝鈎子
	private void Start()
	{
		if (hHookKey != 0)
		{
			//Unhook the previouse one
			this.Stop();
		}
		hookKeyDeleg = new HookKeyProc(HookKeyProcedure);
		hHookKey = SetWindowsHookEx(WH_KEYBOARD_LL, hookKeyDeleg, GetModuleHandle(null), 0);
		if (hHookKey == 0)
		{
			throw new SystemException("Failed acquiring of the hook.");
		}
	}
	//拆除鈎子
	private void Stop()
	{
		UnhookWindowsHookEx(hHookKey);
	}
	#endregion

	#region protected and private methods
	private int HookKeyProcedure(int code, IntPtr wParam, IntPtr lParam)
	{
		KBDLLHOOKSTRUCT hookStruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
		if (code < 0)
		{ return CallNextHookEx(hookKeyDeleg, code, wParam, lParam); }
		if (hookStruct.vkCode == 112 || hookStruct.vkCode == 113 ||
			hookStruct.vkCode == 114 || hookStruct.vkCode == 115 || hookStruct.vkCode == 116)
		{
			KeyEvent(hookStruct.vkCode);
		}
		return CallNextHookEx(hookKeyDeleg, code, wParam, lParam);
	}
	#endregion

	#region P/Invoke declarations
	[DllImport("coredll.dll")]
	private static extern int SetWindowsHookEx(int type, HookKeyProc HookKeyProc, IntPtr hInstance, int m);
	//private static extern int SetWindowsHookEx(int type, HookMouseProc HookMouseProc, IntPtr hInstance, int m);
	[DllImport("coredll.dll")]
	private static extern IntPtr GetModuleHandle(string mod);

	[DllImport("coredll.dll")]
	private static extern int CallNextHookEx(HookKeyProc 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;
	public class KeyBoardInfo
	{
		public int vkCode;
		public int scanCode;
		public int flags;
		public int time;
	}
	#endregion
}
           

在界面背景代碼中,對捕獲的按鍵行為進行定義:

HookKeyClass hk = new HookKeyClass();
hk.KeyEvent += new HookKeyClass.KeyEventHandler(hk_KeyEvent);

private void hk_KeyEvent(int KeyValue)
{
	if (KeyValue == 112)
	{
		// do something
	}
	else if (KeyValue == 113)
	{
		// do something
	}
	else if (KeyValue == 114)
	{
		// do something
	}
	else if (KeyValue == 115)
	{
		// do something
	}
	else if (KeyValue == 116)
	{
		// do something
	}
}
           

繼續閱讀