相信以前用过VB、Delphi,特别是VC的程序员应该对钩子程序都不陌生。在C#中我们同样可以使用钩子程序来实现特殊效果,比如当用户按下某个特殊键时提示,比如关闭应用程序前提示等。 public enum HookType : int { 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_HARDWARE = 8, WH_DEBUG = 9, WH_SHELL = 10, WH_FOREGROUNDIDLE = 11, WH_CALLWNDPROCRET = 12, WH_KEYBOARD_LL = 13, WH_MOUSE_LL = 14 } public enum VirtualKeys { VK_SHIFT = 0x10, VK_CONTROL = 0x11, VK_MENU = 0x12, //ALT VK_PAUSE = 0x13, VK_CAPITAL = 0x14 } public struct CWPSTRUCT { public IntPtr lparam; public IntPtr wparam; public int message; public IntPtr hwnd; } 二、加入自己定义的委托和事件参数 public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam); public delegate void HookEventHandler(object sender, HookEventArgs e); public class HookEventArgs : EventArgs { public int HookCode; public IntPtr wParam; public IntPtr lParam; public Keys key; public bool bAltKey; public bool bCtrlKey; } 三、实现自己的钩子类 这一步是最重要的,要使用钩子,我们需要引用user32.dll中的相应方法: [DllImport("user32.dll")] SetWindowsHookEx是注册一个钩子程序,UnhookWindowsHookEx是释放钩子程序,CallNextHookEx调用钩子的后续事件处理,GetKeyState得到所按的虚键static extern IntPtr SetWindowsHookEx(HookType hook, HookProc callback, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll")] static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll")] static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] static extern short GetKeyState(VirtualKeys nVirtKey); 然后就可以调用这些方法来实现钩子程序,比如注册一个钩子可以调用: m_hook = SetWindowsHookEx(m_hooktype, m_hookproc, IntPtr.Zero, (uint)AppDomain.GetCurrentThreadId()); 其中m_hooktype就是HookType中定义的类型,m_hookproc就是实际的钩子处理程序:m_hookproc = new HookProc(KeyHookProcedure); 最关键的就是KeyHookProcedure等钩子处理程序: protected int KeyHookProcedure(int code, IntPtr wParam, IntPtr lParam) 在这个事件中可以取得消息的参数,特别是按键的值,然后通过HookInvoked委托调用事件实际的处理程序{ if (code != 0) { return CallNextHookEx(m_hook, code, wParam, lParam); } if (HookInvoked != null) { Keys key = (Keys)wParam.ToInt32(); HookEventArgs eventArgs = new HookEventArgs(); eventArgs.key = key; eventArgs.lParam = lParam; eventArgs.wParam = wParam; eventArgs.HookCode = code; eventArgs.bAltKey = GetKeyState(VirtualKeys.VK_MENU) <= -127; eventArgs.bCtrlKey = GetKeyState(VirtualKeys.VK_CONTROL) <= -127; HookInvoked(this, eventArgs); } return CallNextHookEx(m_hook, code, wParam, lParam); } 四、在应用程序中调用钩子类 我们可以在自己的form中声明两个钩子对象 private MyHook callProcHook = new MyHook(HookType.WH_CALLWNDPROC); 然后在初始化时注册钩子:private MyHook keyHook = new MyHook(HookType.WH_KEYBOARD); private void Form1_Load(object sender, EventArgs e) { keyHook.HookInvoked += new HookEventHandler(keyHook_HookInvoked); keyHook.Install(); callProcHook.HookInvoked += new HookEventHandler(callProcHook_HookInvoked); callProcHook.Install(); } 然后就是实际的钩子事件: private void keyHook_HookInvoked(object sender, HookEventArgs e)
{ if (e.key == Keys.F4 && e.bAltKey) //Alt + F4 { this.WindowState = FormWindowState.Minimized; } } private void callProcHook_HookInvoked(object sender, HookEventArgs e) { unsafe { CWPSTRUCT* message = (CWPSTRUCT*)e.lParam; if (message != null) { if (message->message == WM_CLOSE) { (sender as MyHook).CallNextProc = false; MessageBox.Show("程序即将关闭!"); } } } } 这样我们就可以通过钩子实现一些相对底层的应用。 1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Text; 7using System.Windows.Forms; 8using System.Runtime.InteropServices; 9 10namespace HookTest 11{ 12 public partial class Form1 : Form 13 { 14 消息定义(WinUser.h中定义)#region 消息定义(WinUser.h中定义) 15 private const int WM_PAINT = 0x000F; 16 private const int WM_CLOSE = 0x0010; 17 private const int WM_QUIT = 0x0012; 18 private const int WM_DESTROY = 0x0002; 19 #endregion 20 21 private MyHook callProcHook = new MyHook(HookType.WH_CALLWNDPROC); 22 private MyHook keyHook = new MyHook(HookType.WH_KEYBOARD); 23 24 public Form1() 25 { 26 InitializeComponent(); 27 } 28 29 private void Form1_Load(object sender, EventArgs e) 30 { 31 keyHook.HookInvoked += new HookEventHandler(keyHook_HookInvoked); 32 keyHook.Install(); 33 34 callProcHook.HookInvoked += new HookEventHandler(callProcHook_HookInvoked); 35 callProcHook.Install(); 36 } 37 38 private void keyHook_HookInvoked(object sender, HookEventArgs e) 39 { 40 if (e.key == Keys.F4 && e.bAltKey) //Alt + F4 41 { 42 this.WindowState = FormWindowState.Minimized; 43 } 44 } 45 46 private void callProcHook_HookInvoked(object sender, HookEventArgs e) 47 { 48 unsafe 49 { 50 CWPSTRUCT* message = (CWPSTRUCT*)e.lParam; 51 if (message != null) 52 { 53 if (message->message == WM_CLOSE) 54 { 55 (sender as MyHook).CallNextProc = false; 56 MessageBox.Show("程序即将关闭!"); 57 } 58 } 59 } 60 } 61 62 } 63 64 消息结构体(参照WinUser.h中定义)#region 消息结构体(参照WinUser.h中定义) 65 public struct CWPSTRUCT 66 { 67 public IntPtr lparam; 68 public IntPtr wparam; 69 public int message; 70 public IntPtr hwnd; 71 } 72 #endregion 73 74 钩子类型的枚举#region 钩子类型的枚举 75 public enum HookType : int 76 { 77 WH_JOURNALRECORD = 0, 78 WH_JOURNALPLAYBACK = 1, 79 WH_KEYBOARD = 2, 80 WH_GETMESSAGE = 3, 81 WH_CALLWNDPROC = 4, 82 WH_CBT = 5, 83 WH_SYSMSGFILTER = 6, 84 WH_MOUSE = 7, 85 WH_HARDWARE = 8, 86 WH_DEBUG = 9, 87 WH_SHELL = 10, 88 WH_FOREGROUNDIDLE = 11, 89 WH_CALLWNDPROCRET = 12, 90 WH_KEYBOARD_LL = 13, 91 WH_MOUSE_LL = 14 92 } 93 #endregion 94 95 虚键值的定义(参照WinUser.h中定义)#region 虚键值的定义(参照WinUser.h中定义) 96 public enum VirtualKeys 97 { 98 VK_SHIFT = 0x10, 99 VK_CONTROL = 0x11, 100 VK_MENU = 0x12, //ALT 101 VK_PAUSE = 0x13, 102 VK_CAPITAL = 0x14 103 } 104 #endregion 105 106 钩子委托#region 钩子委托 107 public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam); 108 public delegate void HookEventHandler(object sender, HookEventArgs e); 109 #endregion 110 111 钩子事件参数#region 钩子事件参数 112 public class HookEventArgs : EventArgs 113 { 114 public int HookCode; 115 public IntPtr wParam; 116 public IntPtr lParam; 117 public Keys key; 118 public bool bAltKey; 119 public bool bCtrlKey; 120 } 121 #endregion 122 123 钩子类#region 钩子类 124 public class MyHook 125 { 126 调用Windows API#region 调用Windows API 127 [DllImport("user32.dll")] 128 static extern IntPtr SetWindowsHookEx(HookType hook, HookProc callback, IntPtr hMod, uint dwThreadId); 129 130 [DllImport("user32.dll")] 131 static extern bool UnhookWindowsHookEx(IntPtr hhk); 132 133 [DllImport("user32.dll")] 134 static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); 135 136 [DllImport("user32.dll")] 137 static extern short GetKeyState(VirtualKeys nVirtKey); 138 #endregion 139 140 局部变量#region 局部变量 141 private IntPtr m_hook; 142 private HookType m_hooktype; 143 private HookProc m_hookproc; 144 145 private bool _bCallNext; 146 147 public bool CallNextProc 148 { 149 get { return _bCallNext; } 150 set { _bCallNext = value; } 151 } 152 153 #endregion 154 155 public event HookEventHandler HookInvoked; 156 157 public void Install() 158 { 159 m_hook = SetWindowsHookEx(m_hooktype, m_hookproc, IntPtr.Zero, (uint)AppDomain.GetCurrentThreadId()); 160 } 161 162 public void Uninstall() 163 { 164 if (m_hook != IntPtr.Zero) 165 { 166 UnhookWindowsHookEx(m_hook); 167 } 168 } 169 170 public MyHook(HookType HookType) 171 { 172 m_hooktype = HookType; 173 if (m_hooktype == HookType.WH_KEYBOARD) 174 { 175 m_hookproc = new HookProc(KeyHookProcedure); 176 } 177 else if (m_hooktype == HookType.WH_CALLWNDPROC) 178 { 179 m_hookproc = new HookProc(CallProcHookProcedure); 180 } 181 } 182 183 protected int KeyHookProcedure(int code, IntPtr wParam, IntPtr lParam) 184 { 185 if (code != 0) 186 { 187 return CallNextHookEx(m_hook, code, wParam, lParam); 188 } 189 190 if (HookInvoked != null) 191 { 192 Keys key = (Keys)wParam.ToInt32(); 193 HookEventArgs eventArgs = new HookEventArgs(); 194 eventArgs.key = key; 195 eventArgs.lParam = lParam; 196 eventArgs.wParam = wParam; 197 eventArgs.HookCode = code; 198 eventArgs.bAltKey = GetKeyState(VirtualKeys.VK_MENU) <= -127; 199 eventArgs.bCtrlKey = GetKeyState(VirtualKeys.VK_CONTROL) <= -127; 200 HookInvoked(this, eventArgs); 201 } 202 203 return CallNextHookEx(m_hook, code, wParam, lParam); 204 } 205 206 protected int CallProcHookProcedure(int code, IntPtr wParam, IntPtr lParam) 207 { 208 try 209 { 210 CallNextProc = true; 211 if (HookInvoked != null) 212 { 213 HookEventArgs eventArgs = new HookEventArgs(); 214 eventArgs.lParam = lParam; 215 eventArgs.wParam = wParam; 216 eventArgs.HookCode = code; 217 HookInvoked(this, eventArgs); 218 } 219 220 if (CallNextProc) 221 { 222 return CallNextHookEx(m_hook, code, wParam, lParam); 223 } 224 else 225 { 226 //return 1; 227 return CallNextHookEx(IntPtr.Zero, code, wParam, lParam); 228 } 229 } 230 catch (Exception ex) 231 { 232 MessageBox.Show(ex.Message); 233 return 0; 234 } 235 } 236 } 237 #endregion 238}
|
|
来自: kittywei > 《111.20-c#》