接上文
今天突然发现键盘控制不行了,结果还是那个问题搞的鬼,原以为解决了,但是紧接着问题又来了,汗颜啊,将钩子封装成dll
前台调用实例如下
CHW.HookHelper hook; //钩子
<span style="font-family:Microsoft YaHei;font-size:18px;"><span style="font-family:Microsoft YaHei;font-size:18px;">private void MainForm_Activated(object sender, EventArgs e) { //注册事件 hook = new CHW.HookHelper(); hook.SetHook(); hook.OnKeyDownEvent += new KeyEventHandler(hook_OnKeyDownEvent); hook.OnKeyUpEvent += new KeyEventHandler(hook_OnKeyUpEvent); }</span></span>
<span style="font-family:Microsoft YaHei;font-size:18px;"><pre name="code" class="csharp">private void MainForm_Leave(object sender, EventArgs e) { //注销钩子事件 hook.UnHook(); } void hook_OnKeyUpEvent(object sender, KeyEventArgs e) { if (chkbAllowKeyboard.Checked) { //按了左键 按了右键 按了上键 按了下键 之后放起操作 if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Right || e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) btn_MouseUp(sender, null); } } /// <summary> /// 钩子程序控制,键盘作用 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void hook_OnKeyDownEvent(object sender, KeyEventArgs e) { if (chkbAllowKeyboard.Checked) { if (e.KeyCode == Keys.Left) { //按下左键 btnLeft.Focus(); btnLeft_MouseDown(sender, null); } if (e.KeyCode == Keys.Right) { //按下右键 btnRight.Focus(); btnRight_MouseDown(sender, null); } if (e.KeyCode == Keys.Up) { //按下上键 btnFront.Focus(); btnFront_MouseDown(sender, null); } if (e.KeyCode == Keys.Down) { //按下下键 btnBack.Focus(); btnBack_MouseDown(sender, null); } } } </span>
然后经过一般搜索查找,方法如下:
<span style="font-family:Microsoft YaHei;font-size:18px;"><pre name="code" class="csharp">private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) { try { //如果该消息被丢弃(nCode<0)或者没有事件绑定处理程序则不会触发事件 if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null)) { KeyboardHookStruct KeyDataFromHook = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); Keys keyData = (Keys)KeyDataFromHook.vkCode; //按下控制键 if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) { if (IsCtrlAltShiftKeys(keyData) && preKeysList.IndexOf(keyData) == -1) preKeysList.Add(keyData); } //WM_KEYDOWN和WM_SYSKEYDOWN消息,将会引发OnKeyDownEvent事件 if (OnKeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) { KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData)); OnKeyDownEvent(this, e); } //WM_KEYDOWN消息将引发OnKeyPressEvent if (OnKeyPressEvent != null && wParam == WM_KEYDOWN) { byte[] keyState = new byte[256]; GetKeyboardState(keyState); byte[] inBuffer = new byte[2]; if (ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1) { KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]); OnKeyPressEvent(this, e); } } //松开控制键 if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)) { if (IsCtrlAltShiftKeys(keyData)) { for (int i = preKeysList.Count - 1; i >= 0; i--) { if (preKeysList[i] == keyData) preKeysList.RemoveAt(i); } } } //WM_KEYUP和WM_SYSKEYUP消息,将引发OnKeyUpEvent事件 if (OnKeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)) { KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData)); OnKeyUpEvent(this, e); } } <strong> return CallNextHookEx(hHook, nCode, wParam, lParam); //调用下一个钩子函数,如果返回非0,就是丢弃该消息,此时windows不会处理该消息</strong> //return 0; } catch (Exception) { return 0; } } 目前测试在Win7+VS2010调试会报错,运行编译后文件没有问题,在XP+VS2010下调试会报错,运行编译后文件没有问题</span>
</pre><pre name="code" class="csharp"><span style="font-family:Microsoft YaHei;font-size:18px;">如果将上述修改为:return 0;则不会出问题,此时只有一个钩子的话就没有问题,如果有多个钩子大于2个以上就会有问题了</span>
</pre><p><span style="font-family:Microsoft YaHei;font-size:18px;"></span></p><p><span style="font-family:Microsoft YaHei;font-size:18px;">上篇文章代码中出现问题的部分代码改成源代码如下:</span></p><p><pre name="code" class="csharp"><span style="font-family:Microsoft YaHei;font-size:18px;">public void SetHook() { //KeyboardHookDelegate = KeyboardHookProc; KeyboardHookDelegate = new HookProc(KeyboardHookProc); Process cProcess = Process.GetCurrentProcess(); ProcessModule cModule = cProcess.MainModule; IntPtr intPtr = GetModuleHandle(cModule.ModuleName); hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookDelegate, intPtr, 0); if (hHook == 0) { UnHook(); //throw new Exception(Marshal.GetLastWin32Error().ToString()); } }</span>
时间: 2024-11-15 04:37:09