当前位置 博文首页 > unity工具人的博客:unity中使用c#钩子
目的:解决在应用程序最小化后无法监听到系统按键事件的情况
解决问题的过程很好笑
我先找到了第一个方法
脚本一:
//使用方法,脚本挂在场景中物体上即可
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
//using System.Windows.Forms;
using UnityEngine;
public class InterceptKeys : MonoBehaviour
{
//安装钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
//卸载钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
//向下传递钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
//获取程序集模块的句柄
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
//全局钩子键盘为13
private const int WH_KEYBOARD_LL = 13;
//按下键
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
void Start()
{
_hookID = SetHook(_proc);
}
void OnApplicationQuit()
{
UnhookWindowsHookEx(_hookID);
}
//安装Hook,用于截获键盘。
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
//nCode>0表示此消息已由Hook函数处理了,不会交给Windows窗口过程处理了
//nCode=0则表示消息继续传递给Window消息处理函数
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
//UnityEngine.Debug.Log("Keydown:" + vkCode);
switch (vkCode)
{
case 65:
Debug.Log("A");
break;
case 66:
Debug.Log("B");
break;
case 67:
Debug.Log("C");
break;
case 68:
Debug.Log("D");
break;
case 69:
Debug.Log("E");
break;
case 70:
Debug.Log("F");
break;
case 71:
Debug.Log("G");
break;
case 72:
Debug.Log("H");
break;
case 73:
Debug.Log("I");
break;
case 74:
Debug.Log("J");
break;
case 75:
Debug.Log("K");
break;
case 76:
Debug.Log("L");
break;
case 77:
Debug.Log("M");
break;
case 78:
Debug.Log("N");
break;
case 79:
Debug.Log("O");
break;
case 80:
Debug.Log("P");
break;
case 81:
Debug.Log("Q");
break;
case 82:
Debug.Log("R");
break;
case 83:
Debug.Log("S");
break;
case 84:
Debug.Log("T");
break;
case 85:
Debug.Log("U");
break;
case 86:
Debug.Log("V");
break;
case 87:
Debug.Log("W");
break;
case 88:
Debug.Log("X");
break;
case 89:
Debug.Log("Y");
break;
case 90:
Debug.Log("Z");
break;
default:
break;
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);//传给下一个钩子
}
}
上方的脚本已经能够满足对键盘上26个按键的监听了。如果不够用,可以选择对照ASCII表进行补充!
特点:最后被按下并一直按住的键会不停输出,这在我所开发的项目中不合适
你也可以参考第二个写法,这里有鼠标相关的事件
脚本二:
//使用方式
//1.在窗口 新建按钮(开始hook) 点击事件中执行Hook_Start
//2.在窗口 新建按钮(关闭hook) 点击事件中执行Hook_Clear
//3.在KeyBoardHookProc 中编写hook到键盘要进行的操作
//4.在MouseHookProc 中编写hook到鼠标要进行的操作
//一些依赖项
[DllImport("user32.dll")]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll")]
public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
public static extern int GetCurrentThreadId