.NET 的钩子组件……(封装起来使得你不用写代码即可完成钩子的设置)
2008-12-24 02:04 Tsanie 阅读(3398) 评论(24) 编辑 收藏 举报开发中我们很多时候会遇到使用钩子的情况。
用户按下了个按键,我怎么捕捉的到?好,如果焦点在自己的Form里的话,简单,重写ProcessDialogKey方法即可。。如果焦点在其他应用程序呢,Windows不会给我的Form发送按键消息,想捕捉这个按键就可以用钩子了。。。
同样,捕获鼠标也是如此。。不仅是键盘鼠标消息,挂上WH_GETMESSAGE钩子之后我们可以获得其他更多的消息。
前两天看到一个VB写的类,把它给改成C#的了,以组件(Component)形式使用,直接拖到设计器里就好,然后,给这个组件添加事件(KeyUp、KeyDown、MouseUp……)。那么当用户有这些动作的时候就会触发这些事件了,用起来是不是很方便……
设计预览:(像Timer组件一样简简单单的拖进来即可)
代码:
1/**//*
2 * Copyright (c) 2008 黑色珊瑚::Tsorgy.Utils, Reserved.
3 *
4 * Filename: @(#)Hook.cs
5 * Create by: TsOrgY
6 * Email: tsorgy@gmail.com
7 * Date: 2008/12/20 16:30:09
8 *
9 * Classname: Hook
10 * Description: 钩子组件.
11 *
12 */
13
14using System;
15using System.Runtime.InteropServices;
16using System.Reflection;
17using System.ComponentModel;
18
19namespace Tsorgy.Utils {
20
21 /**//// <summary>
22 /// 钩子工具类.
23 /// </summary>
24 [DefaultEvent("KeyUp")]
25 [DefaultProperty("Tag")]
26 public class Hook : Component {
27 * 属性 *#region * 属性 *
28 private bool _enabled = true;
29 /**//// <summary>
30 /// 获取或设置一个布尔值,表示该钩子是否可用.
31 /// </summary>
32 [Description("一个布尔值,表示该钩子是否可用。")]
33 [Category("Behavior")]
34 [DefaultValue(true)]
35 public bool Enabled {
36 get { return _enabled; }
37 set {
38 if (_enabled == value)
39 return;
40 _enabled = value;
41 if (!this.DesignMode) {
42 if (value)
43 SetHook();
44 else
45 RemoveHook();
46 }
47 }
48 }
49
50 /**//// <summary>
51 /// 获取或设置一个任意字符串,表示某种类型的用户状态.
52 /// </summary>
53 [Description("任意字符串,表示某种类型的用户状态。")]
54 [Localizable(false)]
55 [Bindable(true)]
56 [TypeConverter(typeof(StringConverter))]
57 [DefaultValue((string) null)]
58 public object Tag { get; set; }
59 #endregion
60
61 * 事件 *#region * 事件 *
62 public delegate void KeyDownHandler(int keyCode, ShiftKey shift);
63 public delegate void KeyUpHandler(int keyCode, ShiftKey shift);
64 public delegate void SystemKeyDownHandler(int keyCode);
65 public delegate void SystemKeyUpHandler(int keyCode);
66 public delegate void MouseDownHandler(Button button, ShiftKey shift, int x, int y);
67 public delegate void MouseUpHandler(Button button, ShiftKey shift, int x, int y);
68 public delegate void MouseMoveHandler(Button button, ShiftKey shift, int x, int y);
69
70 /**//// <summary>
71 /// 当键盘按下时触发.
72 /// </summary>
73 [Description("键盘按下时触发")]
74 [Category("Behavior")]
75 public event KeyDownHandler KeyDown;
76 /**//// <summary>
77 /// 当键盘弹起时触发.
78 /// </summary>
79 [Description("键盘弹起时触发")]
80 [Category("Behavior")]
81 public event KeyUpHandler KeyUp;
82 /**//// <summary>
83 /// 当系统键盘按下时触发.
84 /// </summary>
85 [Description("系统键盘按下时触发")]
86 [Category("Behavior")]
87 public event SystemKeyDownHandler SystemKeyDown;
88 /**//// <summary>
89 /// 当系统键盘弹起时触发.
90 /// </summary>
91 [Description("系统键盘弹起时触发")]
92 [Category("Behavior")]
93 public event SystemKeyUpHandler SystemKeyUp;
94 /**//// <summary>
95 /// 当鼠标按下时触发.
96 /// </summary>
97 [Description("鼠标按下时触发")]
98 [Category("Behavior")]
99 public event MouseDownHandler MouseDown;
100 /**//// <summary>
101 /// 当鼠标弹起时触发.
102 /// </summary>
103 [Description("鼠标弹起时触发")]
104 [Category("Behavior")]
105 public event MouseUpHandler MouseUp;
106 /**//// <summary>
107 /// 当鼠标移动时触发.
108 /// </summary>
109 [Description("鼠标移动时触发")]
110 [Category("Behavior")]
111 public event MouseMoveHandler MouseMove;
112 #endregion
113
114 * 公共方法 *#region * 公共方法 *
115 /**//// <summary>
116 /// 设置钩子.
117 /// </summary>
118 /// <returns></returns>
119 public bool SetHook() {
120 bool rtn = true;
121 if (hJournalHook != 0 || hAppHook != 0)
122 rtn = rtn && RemoveHook();
123 if (rtn) {
124 IntPtr instance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);
125 hJournalHook = SetWindowsHookEx(WH_JOURNALRECORD, procJournal, instance, 0);
126 hAppHook = SetWindowsHookEx(WH_GETMESSAGE, procAppHook, instance, GetCurrentThreadId());
127 }
128
129 return rtn && hJournalHook != 0 && hAppHook != 0;
130 }
131
132 /**//// <summary>
133 /// 卸载钩子.
134 /// </summary>
135 public bool RemoveHook() {
136 bool rtn = UnhookWindowsHookEx(hAppHook);
137 rtn = rtn && UnhookWindowsHookEx(hJournalHook);
138
139 return rtn;
140 }
141 #endregion
142
143 - 枚举 -#region - 枚举 -
144 /**//// <summary>
145 /// 上档键枚举.
146 /// </summary>
147 public enum ShiftKey {
148 None = 0,
149 Shift = 1,
150 Control = 2,
151 ControlShift = 3,
152 Menu = 4,
153 MenuShift = 5,
154 ControlMenu = 6,
155 ControlMenuShift = 7
156 }
157
158 /**//// <summary>
159 /// 当前鼠标键枚举.
160 /// </summary>
161 public enum Button {
162 Left = 1,
163 Right = 2,
164 LeftRight = 3,
165 Middle = 4,
166 LeftMiddle = 5,
167 RightMiddle = 6,
168 LeftRightMiddle = 7
169 }
170 #endregion
171
172 - API 相关 -#region - API 相关 -
173 /**//// <summary>
174 /// 消息类型.
175 /// </summary>
176 private enum MessageType {
177 WM_CANCELJOURNAL = 0x4B,
178 WM_KEYDOWN = 0x100,
179 WM_KEYUP = 0x101,
180 WM_MOUSEMOVE = 0x200,
181 WM_LBUTTONDOWN = 0x201,
182 WM_LBUTTONUP = 0x202,
183 WM_LBUTTONDBLCLK = 0x203,
184 WM_RBUTTONDOWN = 0x204,
185 WM_RBUTTONUP = 0x205,
186 WM_RBUTTONDBLCLK = 0x206,
187 WM_MBUTTONDOWN = 0x207,
188 WM_MBUTTONUP = 0x208,
189 WM_MBUTTONDBLCLK = 0x209,
190 WM_MOUSEWHEEL = 0x20A,
191 WM_SYSTEMKEYDOWN = 0x104,
192 WM_SYSTEMKEYUP = 0x105
193 }
194 // API 类型.
195 /**//// <summary>
196 /// API 点.
197 /// </summary>
198 private struct PointApi {
199 public int x { get; set; }
200 public int y { get; set; }
201 }
202 /**//// <summary>
203 /// 消息.
204 /// </summary>
205 private struct TMsg {
206 public int hwnd { get; set; }
207 public int message { get; set; }
208 public int wParam { get; set; }
209 public int lParam { get; set; }
210 public int time { get; set; }
211 public PointApi pt { get; set; }
212 }
213 /**//// <summary>
214 /// 事件消息.
215 /// </summary>
216 private struct EventMsg {
217 public int wMsg { get; set; }
218 public int lParamLow { get; set; }
219 public int lParamHigh { get; set; }
220 public int msgTime { get; set; }
221 public int hWndMsg { get; set; }
222 }
223
224 // API 函数声明.
225 public delegate int HookProc(int nCode, int wParam, IntPtr lParam);
226
227 [DllImport("user32.dll")]
228 private static extern int CallNextHookEx(int hHook, int nCode, int wParam, IntPtr lParam);
229 [DllImport("user32.dll")]
230 private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
231 [DllImport("user32.dll")]
232 private static extern bool UnhookWindowsHookEx(int idHook);
233 [DllImport("User32.dll")]
234 private static extern short GetAsyncKeyState(int vKey);
235 [DllImport("kernel32.dll")]
236 public static extern int GetCurrentThreadId();
237
238 // API 常量.
239 private const int WH_JOURNALRECORD = 0;
240 private const int WH_GETMESSAGE = 3;
241 #endregion
242
243 - 回调函数 -#region - 回调函数 -
244 /**//// <summary>
245 /// Journal 回调.
246 /// </summary>
247 /// <param name="nCode"></param>
248 /// <param name="wParam"></param>
249 /// <param name="lParam"></param>
250 /// <returns></returns>
251 private int JournalRecordProc(int nCode, int wParam, IntPtr lParam) {
252 if (nCode < 0) {
253 return CallNextHookEx(hJournalHook, nCode, wParam, lParam);
254 }
255 FireEvent(lParam);
256 return CallNextHookEx(hJournalHook, nCode, wParam, lParam);
257 }
258
259 /**//// <summary>
260 /// 应用程序钩子 回调.
261 /// </summary>
262 /// <param name="nCode"></param>
263 /// <param name="wParam"></param>
264 /// <param name="lParam"></param>
265 /// <returns></returns>
266 private int AppHookProc(int nCode, int wParam, IntPtr lParam) {
267 if (nCode < 0) {
268 return CallNextHookEx(hAppHook, nCode, wParam, lParam);
269 }
270 TMsg msg = (TMsg) Marshal.PtrToStructure(lParam, typeof(TMsg));
271 switch ((MessageType) msg.message) {
272 case MessageType.WM_CANCELJOURNAL:
273 if (wParam == 1)
274 FireEvent(new IntPtr((int) MessageType.WM_CANCELJOURNAL));
275 break;
276 default:
277 break;
278 }
279 return CallNextHookEx(hAppHook, nCode, wParam, lParam);
280 }
281
282 #endregion
283
284 - 全局变量 -#region - 全局变量 -
285 // 全局变量.
286 private int hJournalHook, hAppHook;
287 private HookProc procJournal, procAppHook;
288 #endregion
289
290 - 构造方法 -#region - 构造方法 -
291 /**//// <summary>
292 /// 初始化 <see cref="StepMania.Utils.Hook"/> 类的新实例.
293 /// </summary>
294 public Hook() {
295 if (!this.DesignMode) {
296 hJournalHook = 0;
297 hAppHook = 0;
298 procAppHook = new HookProc(AppHookProc);
299 procJournal = new HookProc(JournalRecordProc);
300
301 SetHook();
302 }
303 }
304 #endregion
305
306 - 私有方法 -#region - 私有方法 -
307 /**//// <summary>
308 /// 取得当前上档键状态.
309 /// </summary>
310 /// <returns></returns>
311 private ShiftKey GetShiftNow() {
312 ShiftKey shift = ShiftKey.None;
313 if (GetAsyncKeyState(0x10) != 0) //Shift
314 shift |= ShiftKey.Shift;
315 if (GetAsyncKeyState(0x11) != 0) //Control
316 shift |= ShiftKey.Control;
317 if (GetAsyncKeyState(0x12) != 0) //Menu
318 shift |= ShiftKey.Menu;
319 return shift;
320 }
321
322 /**//// <summary>
323 /// 取得当前鼠标按钮状态.
324 /// </summary>
325 /// <returns></returns>
326 private Button GetButtonNow() {
327 Button button = Button.Left;
328 if (GetAsyncKeyState(0x1) != 0)
329 button |= Button.Left;
330 if (GetAsyncKeyState(0x2) != 0)
331 button |= Button.Right;
332 if (GetAsyncKeyState(0x4) != 0)
333 button |= Button.Middle;
334 return button;
335 }
336
337 /**//// <summary>
338 /// 得到消息,分析后触发事件.
339 /// </summary>
340 /// <param name="lParam"></param>
341 private void FireEvent(IntPtr lParam) {
342 if (lParam.ToInt32() == (int) MessageType.WM_CANCELJOURNAL) {
343 hJournalHook = 0;
344 SetHook();
345 return;
346 }
347 EventMsg EMSG = (EventMsg) Marshal.PtrToStructure(lParam, typeof(EventMsg));
348 switch ((MessageType) EMSG.wMsg) {
349 case MessageType.WM_KEYDOWN:
350 if (KeyDown != null)
351 KeyDown(EMSG.lParamLow & 0xFF, GetShiftNow());
352 break;
353 case MessageType.WM_KEYUP:
354 if (KeyUp != null)
355 KeyUp(EMSG.lParamLow & 0xFF, GetShiftNow());
356 break;
357 case MessageType.WM_MOUSEMOVE:
358 if (MouseMove != null)
359 MouseMove(GetButtonNow(), GetShiftNow(), EMSG.lParamLow, EMSG.lParamHigh);
360 break;
361 case MessageType.WM_LBUTTONDOWN:
362 case MessageType.WM_RBUTTONDOWN:
363 case MessageType.WM_MBUTTONDOWN:
364 if (MouseDown != null)
365 MouseDown((Button) (Math.Pow(2, (EMSG.wMsg - 513) / 3)), GetShiftNow(),
366 EMSG.lParamLow, EMSG.lParamHigh);
367 break;
368 case MessageType.WM_LBUTTONUP:
369 case MessageType.WM_RBUTTONUP:
370 case MessageType.WM_MBUTTONUP:
371 if (MouseUp != null)
372 MouseUp((Button) (Math.Pow(2, (EMSG.wMsg - 513) / 3)), GetShiftNow(),
373 EMSG.lParamLow, EMSG.lParamHigh);
374 break;
375 case MessageType.WM_SYSTEMKEYDOWN:
376 if (SystemKeyDown != null)
377 SystemKeyDown(EMSG.lParamLow & 0xFF);
378 break;
379 case MessageType.WM_SYSTEMKEYUP:
380 if (SystemKeyUp != null)
381 SystemKeyUp(EMSG.lParamLow & 0xFF);
382 break;
383 default:
384 break;
385 }
386 }
387 #endregion
388
389 | 重写方法 |#region | 重写方法 |
390 /**//// <summary>
391 /// 释放由 <see cref="T:System.ComponentModel.Component"></see> 占用的非托管资源,还可以另外再释放托管资源.
392 /// </summary>
393 /// <param name="disposing">为 true 则释放托管资源和非托管资源;为 false 则仅释放非托管资源。</param>
394 protected override void Dispose(bool disposing) {
395 RemoveHook();
396 base.Dispose(disposing);
397 }
398 #endregion
399 }
400}
401
2 * Copyright (c) 2008 黑色珊瑚::Tsorgy.Utils, Reserved.
3 *
4 * Filename: @(#)Hook.cs
5 * Create by: TsOrgY
6 * Email: tsorgy@gmail.com
7 * Date: 2008/12/20 16:30:09
8 *
9 * Classname: Hook
10 * Description: 钩子组件.
11 *
12 */
13
14using System;
15using System.Runtime.InteropServices;
16using System.Reflection;
17using System.ComponentModel;
18
19namespace Tsorgy.Utils {
20
21 /**//// <summary>
22 /// 钩子工具类.
23 /// </summary>
24 [DefaultEvent("KeyUp")]
25 [DefaultProperty("Tag")]
26 public class Hook : Component {
27 * 属性 *#region * 属性 *
28 private bool _enabled = true;
29 /**//// <summary>
30 /// 获取或设置一个布尔值,表示该钩子是否可用.
31 /// </summary>
32 [Description("一个布尔值,表示该钩子是否可用。")]
33 [Category("Behavior")]
34 [DefaultValue(true)]
35 public bool Enabled {
36 get { return _enabled; }
37 set {
38 if (_enabled == value)
39 return;
40 _enabled = value;
41 if (!this.DesignMode) {
42 if (value)
43 SetHook();
44 else
45 RemoveHook();
46 }
47 }
48 }
49
50 /**//// <summary>
51 /// 获取或设置一个任意字符串,表示某种类型的用户状态.
52 /// </summary>
53 [Description("任意字符串,表示某种类型的用户状态。")]
54 [Localizable(false)]
55 [Bindable(true)]
56 [TypeConverter(typeof(StringConverter))]
57 [DefaultValue((string) null)]
58 public object Tag { get; set; }
59 #endregion
60
61 * 事件 *#region * 事件 *
62 public delegate void KeyDownHandler(int keyCode, ShiftKey shift);
63 public delegate void KeyUpHandler(int keyCode, ShiftKey shift);
64 public delegate void SystemKeyDownHandler(int keyCode);
65 public delegate void SystemKeyUpHandler(int keyCode);
66 public delegate void MouseDownHandler(Button button, ShiftKey shift, int x, int y);
67 public delegate void MouseUpHandler(Button button, ShiftKey shift, int x, int y);
68 public delegate void MouseMoveHandler(Button button, ShiftKey shift, int x, int y);
69
70 /**//// <summary>
71 /// 当键盘按下时触发.
72 /// </summary>
73 [Description("键盘按下时触发")]
74 [Category("Behavior")]
75 public event KeyDownHandler KeyDown;
76 /**//// <summary>
77 /// 当键盘弹起时触发.
78 /// </summary>
79 [Description("键盘弹起时触发")]
80 [Category("Behavior")]
81 public event KeyUpHandler KeyUp;
82 /**//// <summary>
83 /// 当系统键盘按下时触发.
84 /// </summary>
85 [Description("系统键盘按下时触发")]
86 [Category("Behavior")]
87 public event SystemKeyDownHandler SystemKeyDown;
88 /**//// <summary>
89 /// 当系统键盘弹起时触发.
90 /// </summary>
91 [Description("系统键盘弹起时触发")]
92 [Category("Behavior")]
93 public event SystemKeyUpHandler SystemKeyUp;
94 /**//// <summary>
95 /// 当鼠标按下时触发.
96 /// </summary>
97 [Description("鼠标按下时触发")]
98 [Category("Behavior")]
99 public event MouseDownHandler MouseDown;
100 /**//// <summary>
101 /// 当鼠标弹起时触发.
102 /// </summary>
103 [Description("鼠标弹起时触发")]
104 [Category("Behavior")]
105 public event MouseUpHandler MouseUp;
106 /**//// <summary>
107 /// 当鼠标移动时触发.
108 /// </summary>
109 [Description("鼠标移动时触发")]
110 [Category("Behavior")]
111 public event MouseMoveHandler MouseMove;
112 #endregion
113
114 * 公共方法 *#region * 公共方法 *
115 /**//// <summary>
116 /// 设置钩子.
117 /// </summary>
118 /// <returns></returns>
119 public bool SetHook() {
120 bool rtn = true;
121 if (hJournalHook != 0 || hAppHook != 0)
122 rtn = rtn && RemoveHook();
123 if (rtn) {
124 IntPtr instance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);
125 hJournalHook = SetWindowsHookEx(WH_JOURNALRECORD, procJournal, instance, 0);
126 hAppHook = SetWindowsHookEx(WH_GETMESSAGE, procAppHook, instance, GetCurrentThreadId());
127 }
128
129 return rtn && hJournalHook != 0 && hAppHook != 0;
130 }
131
132 /**//// <summary>
133 /// 卸载钩子.
134 /// </summary>
135 public bool RemoveHook() {
136 bool rtn = UnhookWindowsHookEx(hAppHook);
137 rtn = rtn && UnhookWindowsHookEx(hJournalHook);
138
139 return rtn;
140 }
141 #endregion
142
143 - 枚举 -#region - 枚举 -
144 /**//// <summary>
145 /// 上档键枚举.
146 /// </summary>
147 public enum ShiftKey {
148 None = 0,
149 Shift = 1,
150 Control = 2,
151 ControlShift = 3,
152 Menu = 4,
153 MenuShift = 5,
154 ControlMenu = 6,
155 ControlMenuShift = 7
156 }
157
158 /**//// <summary>
159 /// 当前鼠标键枚举.
160 /// </summary>
161 public enum Button {
162 Left = 1,
163 Right = 2,
164 LeftRight = 3,
165 Middle = 4,
166 LeftMiddle = 5,
167 RightMiddle = 6,
168 LeftRightMiddle = 7
169 }
170 #endregion
171
172 - API 相关 -#region - API 相关 -
173 /**//// <summary>
174 /// 消息类型.
175 /// </summary>
176 private enum MessageType {
177 WM_CANCELJOURNAL = 0x4B,
178 WM_KEYDOWN = 0x100,
179 WM_KEYUP = 0x101,
180 WM_MOUSEMOVE = 0x200,
181 WM_LBUTTONDOWN = 0x201,
182 WM_LBUTTONUP = 0x202,
183 WM_LBUTTONDBLCLK = 0x203,
184 WM_RBUTTONDOWN = 0x204,
185 WM_RBUTTONUP = 0x205,
186 WM_RBUTTONDBLCLK = 0x206,
187 WM_MBUTTONDOWN = 0x207,
188 WM_MBUTTONUP = 0x208,
189 WM_MBUTTONDBLCLK = 0x209,
190 WM_MOUSEWHEEL = 0x20A,
191 WM_SYSTEMKEYDOWN = 0x104,
192 WM_SYSTEMKEYUP = 0x105
193 }
194 // API 类型.
195 /**//// <summary>
196 /// API 点.
197 /// </summary>
198 private struct PointApi {
199 public int x { get; set; }
200 public int y { get; set; }
201 }
202 /**//// <summary>
203 /// 消息.
204 /// </summary>
205 private struct TMsg {
206 public int hwnd { get; set; }
207 public int message { get; set; }
208 public int wParam { get; set; }
209 public int lParam { get; set; }
210 public int time { get; set; }
211 public PointApi pt { get; set; }
212 }
213 /**//// <summary>
214 /// 事件消息.
215 /// </summary>
216 private struct EventMsg {
217 public int wMsg { get; set; }
218 public int lParamLow { get; set; }
219 public int lParamHigh { get; set; }
220 public int msgTime { get; set; }
221 public int hWndMsg { get; set; }
222 }
223
224 // API 函数声明.
225 public delegate int HookProc(int nCode, int wParam, IntPtr lParam);
226
227 [DllImport("user32.dll")]
228 private static extern int CallNextHookEx(int hHook, int nCode, int wParam, IntPtr lParam);
229 [DllImport("user32.dll")]
230 private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
231 [DllImport("user32.dll")]
232 private static extern bool UnhookWindowsHookEx(int idHook);
233 [DllImport("User32.dll")]
234 private static extern short GetAsyncKeyState(int vKey);
235 [DllImport("kernel32.dll")]
236 public static extern int GetCurrentThreadId();
237
238 // API 常量.
239 private const int WH_JOURNALRECORD = 0;
240 private const int WH_GETMESSAGE = 3;
241 #endregion
242
243 - 回调函数 -#region - 回调函数 -
244 /**//// <summary>
245 /// Journal 回调.
246 /// </summary>
247 /// <param name="nCode"></param>
248 /// <param name="wParam"></param>
249 /// <param name="lParam"></param>
250 /// <returns></returns>
251 private int JournalRecordProc(int nCode, int wParam, IntPtr lParam) {
252 if (nCode < 0) {
253 return CallNextHookEx(hJournalHook, nCode, wParam, lParam);
254 }
255 FireEvent(lParam);
256 return CallNextHookEx(hJournalHook, nCode, wParam, lParam);
257 }
258
259 /**//// <summary>
260 /// 应用程序钩子 回调.
261 /// </summary>
262 /// <param name="nCode"></param>
263 /// <param name="wParam"></param>
264 /// <param name="lParam"></param>
265 /// <returns></returns>
266 private int AppHookProc(int nCode, int wParam, IntPtr lParam) {
267 if (nCode < 0) {
268 return CallNextHookEx(hAppHook, nCode, wParam, lParam);
269 }
270 TMsg msg = (TMsg) Marshal.PtrToStructure(lParam, typeof(TMsg));
271 switch ((MessageType) msg.message) {
272 case MessageType.WM_CANCELJOURNAL:
273 if (wParam == 1)
274 FireEvent(new IntPtr((int) MessageType.WM_CANCELJOURNAL));
275 break;
276 default:
277 break;
278 }
279 return CallNextHookEx(hAppHook, nCode, wParam, lParam);
280 }
281
282 #endregion
283
284 - 全局变量 -#region - 全局变量 -
285 // 全局变量.
286 private int hJournalHook, hAppHook;
287 private HookProc procJournal, procAppHook;
288 #endregion
289
290 - 构造方法 -#region - 构造方法 -
291 /**//// <summary>
292 /// 初始化 <see cref="StepMania.Utils.Hook"/> 类的新实例.
293 /// </summary>
294 public Hook() {
295 if (!this.DesignMode) {
296 hJournalHook = 0;
297 hAppHook = 0;
298 procAppHook = new HookProc(AppHookProc);
299 procJournal = new HookProc(JournalRecordProc);
300
301 SetHook();
302 }
303 }
304 #endregion
305
306 - 私有方法 -#region - 私有方法 -
307 /**//// <summary>
308 /// 取得当前上档键状态.
309 /// </summary>
310 /// <returns></returns>
311 private ShiftKey GetShiftNow() {
312 ShiftKey shift = ShiftKey.None;
313 if (GetAsyncKeyState(0x10) != 0) //Shift
314 shift |= ShiftKey.Shift;
315 if (GetAsyncKeyState(0x11) != 0) //Control
316 shift |= ShiftKey.Control;
317 if (GetAsyncKeyState(0x12) != 0) //Menu
318 shift |= ShiftKey.Menu;
319 return shift;
320 }
321
322 /**//// <summary>
323 /// 取得当前鼠标按钮状态.
324 /// </summary>
325 /// <returns></returns>
326 private Button GetButtonNow() {
327 Button button = Button.Left;
328 if (GetAsyncKeyState(0x1) != 0)
329 button |= Button.Left;
330 if (GetAsyncKeyState(0x2) != 0)
331 button |= Button.Right;
332 if (GetAsyncKeyState(0x4) != 0)
333 button |= Button.Middle;
334 return button;
335 }
336
337 /**//// <summary>
338 /// 得到消息,分析后触发事件.
339 /// </summary>
340 /// <param name="lParam"></param>
341 private void FireEvent(IntPtr lParam) {
342 if (lParam.ToInt32() == (int) MessageType.WM_CANCELJOURNAL) {
343 hJournalHook = 0;
344 SetHook();
345 return;
346 }
347 EventMsg EMSG = (EventMsg) Marshal.PtrToStructure(lParam, typeof(EventMsg));
348 switch ((MessageType) EMSG.wMsg) {
349 case MessageType.WM_KEYDOWN:
350 if (KeyDown != null)
351 KeyDown(EMSG.lParamLow & 0xFF, GetShiftNow());
352 break;
353 case MessageType.WM_KEYUP:
354 if (KeyUp != null)
355 KeyUp(EMSG.lParamLow & 0xFF, GetShiftNow());
356 break;
357 case MessageType.WM_MOUSEMOVE:
358 if (MouseMove != null)
359 MouseMove(GetButtonNow(), GetShiftNow(), EMSG.lParamLow, EMSG.lParamHigh);
360 break;
361 case MessageType.WM_LBUTTONDOWN:
362 case MessageType.WM_RBUTTONDOWN:
363 case MessageType.WM_MBUTTONDOWN:
364 if (MouseDown != null)
365 MouseDown((Button) (Math.Pow(2, (EMSG.wMsg - 513) / 3)), GetShiftNow(),
366 EMSG.lParamLow, EMSG.lParamHigh);
367 break;
368 case MessageType.WM_LBUTTONUP:
369 case MessageType.WM_RBUTTONUP:
370 case MessageType.WM_MBUTTONUP:
371 if (MouseUp != null)
372 MouseUp((Button) (Math.Pow(2, (EMSG.wMsg - 513) / 3)), GetShiftNow(),
373 EMSG.lParamLow, EMSG.lParamHigh);
374 break;
375 case MessageType.WM_SYSTEMKEYDOWN:
376 if (SystemKeyDown != null)
377 SystemKeyDown(EMSG.lParamLow & 0xFF);
378 break;
379 case MessageType.WM_SYSTEMKEYUP:
380 if (SystemKeyUp != null)
381 SystemKeyUp(EMSG.lParamLow & 0xFF);
382 break;
383 default:
384 break;
385 }
386 }
387 #endregion
388
389 | 重写方法 |#region | 重写方法 |
390 /**//// <summary>
391 /// 释放由 <see cref="T:System.ComponentModel.Component"></see> 占用的非托管资源,还可以另外再释放托管资源.
392 /// </summary>
393 /// <param name="disposing">为 true 则释放托管资源和非托管资源;为 false 则仅释放非托管资源。</param>
394 protected override void Dispose(bool disposing) {
395 RemoveHook();
396 base.Dispose(disposing);
397 }
398 #endregion
399 }
400}
401