当前位置 博文首页 > unity工具人的博客:unity中使用c#钩子

    unity工具人的博客:unity中使用c#钩子

    作者:[db:作者] 时间:2021-07-19 22:31

    目的:解决在应用程序最小化后无法监听到系统按键事件的情况
    解决问题的过程很好笑
    我先找到了第一个方法
    脚本一:

    //使用方法,脚本挂在场景中物体上即可
    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
    
    下一篇:没有了