标签:
类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们的问题的解决方法 续集
接上文
今天突然发现键盘控制不行了,结果还是那个问题搞的鬼,原以为解决了,但是紧接着问题又来了,汗颜啊,将钩子封装成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>类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们的问题的解决方法 续集
标签:
原文地址:http://blog.csdn.net/chenhongwu666/article/details/42175053