using System; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Collections.Generic; using System.Diagnostics; namespace EasyHook { public enum HookType { WH_MSGFILTER = -1, WH_JOURNALRECORD = 0, WH_JOURNALPLAYBACK = 1, WH_KEYBOARD = 2, WH_GETMESSAGE = 3, WH_CALLWNDPROC = 4, WH_CBT = 5, WH_SYSMSGFILTER = 6, WH_MOUSE = 7, WH_DEBUG = 9, WH_SHELL = 10, WH_FOREGROUNDIDLE = 11, WH_CALLWNDPROCRET = 12, WH_KEYBOARD_LL = 13, WH_MOUSE_LL = 14 } public class CustomHookProc { private CustomHookProc(){} public delegate void HookProcHandler(int nCode, IntPtr wParam, IntPtr lParam); } public class HookManager { private HookManager(){} static readonly HookManager m_instance = new HookManager(); Dictionary<HookType, _HookProc> m_hooks = new Dictionary<HookType, _HookProc>(); public static HookManager Instance { get { return m_instance; } } public void RegisterHook(HookType a_eHookType, CustomHookProc.HookProcHandler a_pHookProc) { if(!m_hooks.ContainsKey(a_eHookType)) { m_hooks.Add(a_eHookType, new _HookProc(a_eHookType, a_pHookProc)); } else { throw new Exception(string.Format("{0} already exist!", a_eHookType.ToString())); } } public void Unregister(HookType a_eHookType) { m_hooks.Remove(a_eHookType); } } class _HookProc { #region "Declare API for Hook" [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] static extern int SetWindowsHookEx(int idHook, _HookProcHandler lpfn, IntPtr hInstance, int threadId); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] static extern bool UnhookWindowsHookEx(int idHook); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll")] static extern int GetCurrentThreadId(); #endregion #region "Hook Proc" int MyHookProc(int nCode, IntPtr wParam, IntPtr lParam) { if (m_CustomHookProc != null) m_CustomHookProc(nCode, wParam, lParam); return CallNextHookEx(m_HookHandle, nCode, wParam, lParam); } #endregion CustomHookProc.HookProcHandler m_CustomHookProc; delegate int _HookProcHandler(int nCode, IntPtr wParam, IntPtr lParam); _HookProcHandler m_KbdHookProc; int m_HookHandle = 0; public _HookProc(HookType a_eHookType, CustomHookProc.HookProcHandler a_pHookProc) { m_CustomHookProc = a_pHookProc; m_KbdHookProc = new _HookProcHandler(MyHookProc); m_HookHandle = SetWindowsHookEx((int)a_eHookType, m_KbdHookProc, IntPtr.Zero, GetCurrentThreadId()); if (m_HookHandle == 0) { throw new Exception(string.Format("Hook {0} to {1} Error:{2}", a_eHookType.ToString(), a_pHookProc.ToString(), Marshal.GetLastWin32Error())); } } ~_HookProc() { UnhookWindowsHookEx(m_HookHandle); Debug.WriteLine(Marshal.GetLastWin32Error()); m_HookHandle = 0; } } }
using System; using System.Runtime.InteropServices; using System.Windows.Forms; namespace EasyHook { public class KeyboardInfo { private KeyboardInfo() { } [DllImport("user32")] private static extern short GetKeyState(int vKey); public static KeyStateInfo GetKeyState(Keys key) { int vkey = (int)key; if (key == Keys.Alt) { vkey = 0x12; // VK_ALT } short keyState = GetKeyState(vkey); byte[] bits = BitConverter.GetBytes(keyState); bool toggled = bits[0] > 0, pressed = bits[1] > 0; return new KeyStateInfo(key, pressed, toggled); } } public struct KeyStateInfo { Keys m_key; bool m_isPressed, m_isToggled; public KeyStateInfo(Keys key, bool ispressed, bool istoggled) { m_key = key; m_isPressed = ispressed; m_isToggled = istoggled; } public static KeyStateInfo Default { get { return new KeyStateInfo(Keys.None, false, false); } } public Keys Key { get { return m_key; } } public bool IsPressed { get { return m_isPressed; } } public bool IsToggled { get { return m_isToggled; } } } }
using System.Runtime.InteropServices; namespace EasyHook { [StructLayout(LayoutKind.Sequential)] public class POINT { public int x; public int y; } [StructLayout(LayoutKind.Sequential)] public class MouseHookStruct { public POINT pt; public int hwnd; public int wHitTestCode; public int dwExtraInfo; } }
Usage:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { HookManager.Instance.RegisterHook(HookType.WH_KEYBOARD, new CustomHookProc.HookProcHandler(KeyboardHookProc)); HookManager.Instance.RegisterHook(HookType.WH_MOUSE, new CustomHookProc.HookProcHandler(MouseHookProc)); } void KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam) { KeyStateInfo ctrlKey = KeyboardInfo.GetKeyState(Keys.ControlKey); KeyStateInfo altKey = KeyboardInfo.GetKeyState(Keys.Alt); KeyStateInfo shiftKey = KeyboardInfo.GetKeyState(Keys.ShiftKey); KeyStateInfo f8Key = KeyboardInfo.GetKeyState(Keys.F8); if (ctrlKey.IsPressed) { Console.WriteLine("Ctrl Pressed!"); } if (altKey.IsPressed) { Console.WriteLine("Alt Pressed!"); } if (shiftKey.IsPressed) { Console.WriteLine("Shift Pressed!"); } if (f8Key.IsPressed) { Console.WriteLine("F8 Pressed!"); } } void MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam) { MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct)); if (nCode >= 0) { String strCaption = "x = " + MyMouseHookStruct.pt.x.ToString("d") + " y = " + MyMouseHookStruct.pt.y.ToString("d"); Form tempForm = Form.ActiveForm; tempForm.Text = strCaption; } } }