【Unity知识分享】Unity实现全局监听键鼠调用

发布于:2025-09-06 ⋅ 阅读:(16) ⋅ 点赞:(0)

1、实现该功能前,优先学习Unity接入dll调用Window系统接口教程

【Unity知识分享】Unity接入dll调用Window系统接口

2、初始化动态连接库后,进行脚本功能实现

2.1 创建脚本KeyBoardHook.h和KeyBoardHook.cpp,实现功能如下

KeyBoardHook.h

#pragma once
#include <windows.h>

#ifdef MYNATIVE_EXPORTS
#define MY_API __declspec(dllexport)
#else
#define MY_API __declspec(dllimport)
#endif // MYNATIVE_EXPORTS

extern "C" {
	//定义一个回调的函数指针
	typedef void(__stdcall* KeyCallback)(int vkCode);

	MY_API bool InstallHook(HWND hWnd, KeyCallback callback);

	MY_API void UninstallHook();
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);

KeyBoardHook.cpp

#include "KeyBoardHook.h"
//#include <Windows.h>

HHOOK g_hHook = NULL;
HHOOK g_hMouseHook = NULL;
HWND g_hwnd = NULL;
KeyCallback g_callback = nullptr;

extern "C" {
	MY_API bool InstallHook(HWND hwnd, KeyCallback callback)
	{
		g_hwnd = hwnd;
		g_callback = callback;
		g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, GetModuleHandle(NULL), 0);
		g_hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), 0);
		return g_hHook != NULL;
	}

	MY_API void UninstallHook() 
	{
		if (g_hHook) 
		{
			UnhookWindowsHookEx(g_hHook);
			UnhookWindowsHookEx(g_hMouseHook);
			g_hHook = NULL;
			g_hMouseHook = NULL;
			g_callback = nullptr;
		}
	}
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 
{
	if (nCode == HC_ACTION && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
	{
		KBDLLHOOKSTRUCT* kb = (KBDLLHOOKSTRUCT*)lParam;
		OutputDebugStringA("keyboardProc triggered\n");
		if (g_hwnd && g_callback)
		{
			OutputDebugStringA("Calling Unity callback\n");
			g_callback((int)kb->vkCode);
		}
		else
		{
			OutputDebugStringA("g_callback is null\n");
		}
	}
	return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if (nCode == HC_ACTION)
	{
		int vkCode = 0;
		MSLLHOOKSTRUCT* ms = (MSLLHOOKSTRUCT*)lParam;
		switch (wParam)
		{
		case WM_LBUTTONDOWN:
			vkCode = VK_LBUTTON;
			break;
		case WM_RBUTTONDOWN:
			vkCode = VK_RBUTTON;
			break;
		case WM_MBUTTONDOWN:
			vkCode = VK_MBUTTON;
			break;
		default:
			return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
		}

		OutputDebugStringA("MouseProc triggered\n");

		if (g_hwnd && g_callback) 
		{
			OutputDebugStringA("Calling Unity mouse callback\n");
			g_callback(vkCode);
		}
		else
		{
			OutputDebugStringA("g_callback is null\n");
		}

	}
	return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
}

2.2 生成dll包

3、将dll包导入Unity,并实现dll包实现功能

3.1 创建Plugins文件夹,将dll包复制到该文件夹下面

3.2 将dll设置为PC的x64

3.3 创建脚本KeyboardHook,实现具体功能逻辑,代码如下

KeyboardHook

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;

public class KeyboardHook : MonoBehaviour
{
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void KeyCallback(int vkCode);

    [DllImport("UnityDll.dll")]
    private static extern bool InstallHook(IntPtr hwnd, KeyCallback callback);

    [DllImport("UnityDll.dll")]
    private static extern void UninstallHook();

    private static KeyCallback callbackDelegate;
    private IntPtr _hwnd;
    public Text txt_NumberText;
    public Text txt_vkText;
    private int num = 0;

    private Dictionary<int, string> keyCodeToStringDic = new Dictionary<int, string>{
        // 字母键 (A-Z)
        { 65, "A" }, { 66, "B" }, { 67, "C" }, { 68, "D" }, { 69, "E" },
        { 70, "F" }, { 71, "G" }, { 72, "H" }, { 73, "I" }, { 74, "J" },
        { 75, "K" }, { 76, "L" }, { 77, "M" }, { 78, "N" }, { 79, "O" },
        { 80, "P" }, { 81, "Q" }, { 82, "R" }, { 83, "S" }, { 84, "T" },
        { 85, "U" }, { 86, "V" }, { 87, "W" }, { 88, "X" }, { 89, "Y" },
        { 90, "Z" },
 
        // 数字键 (0-9)
        { 48, "0" }, { 49, "1" }, { 50, "2" }, { 51, "3" }, { 52, "4" },
        { 53, "5" }, { 54, "6" }, { 55, "7" }, { 56, "8" }, { 57, "9" },
 
        // 数字小键盘 (NumPad 0-9)
        { 96, "NumPad 0" }, { 97, "NumPad 1" }, { 98, "NumPad 2" },
        { 99, "NumPad 3" }, { 100, "NumPad 4" }, { 101, "NumPad 5" },
        { 102, "NumPad 6" }, { 103, "NumPad 7" }, { 104, "NumPad 8" },
        { 105, "NumPad 9" },
 
        // 功能键 (F1-F12)
        { 112, "F1" }, { 113, "F2" }, { 114, "F3" }, { 115, "F4" },
        { 116, "F5" }, { 117, "F6" }, { 118, "F7" }, { 119, "F8" },
        { 120, "F9" }, { 121, "F10" }, { 122, "F11" }, { 123, "F12" },
 
        // 方向键
        { 38, "Up Arrow" }, { 40, "Down Arrow" },
        { 37, "Left Arrow" }, { 39, "Right Arrow" },
 
        // 特殊键
        { 27, "Escape" }, { 9, "Tab" }, { 20, "Caps Lock" },
        { 16, "Shift" }, { 17, "Control" }, { 18, "Alt" },
        { 91, "Left Windows" }, { 92, "Right Windows" },
        { 93, "Application" }, { 32, "Space" }, { 13, "Enter" },
        { 8, "Backspace" }, { 46, "Delete" }, { 45, "Insert" },
        { 36, "Home" }, { 35, "End" }, { 33, "Page Up" },
        { 34, "Page Down" }, { 44, "Print Screen" }, { 145, "Scroll Lock" },
        { 19, "Pause" }, { 144, "Num Lock" },
 
        // 小键盘操作符
        { 107, "NumPad +" }, { 109, "NumPad -" }, { 106, "NumPad *" },
        { 111, "NumPad /" }, { 110, "NumPad ." },
 
        // 标点符号(美式键盘)
        { 186, ";:" }, { 187, "=+" }, { 188, ",<" },
        { 189, "-_" }, { 190, ".>" }, { 191, "/?" },
        { 192, "~`" }, { 219, "[{" }, { 220, "\\|" },
        { 221, "]}" }, { 222, "'\"" },

        //鼠标按键
        {1, "Left Mouse Key" },{2, "Right Mouse Key" },{4, "Middle Mouse Key" },
    };
 
    private void Awake()
    {
        _hwnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
        callbackDelegate = OnKeyPressed;
        bool res = InstallHook(_hwnd, callbackDelegate);

        if(!res)
        {
            Debug.LogError("钩子安装失败!");
        }
        else
        {
            Debug.Log("钩子安装成功!");
        }
    }

    private void OnDestroy()
    {
        UninstallHook();
    }

    private string GetKeyName(int vkCode)
    {
        if(keyCodeToStringDic.ContainsKey(vkCode))
            return keyCodeToStringDic[vkCode];
        return "Null";
    }

    private void OnKeyPressed(int vkCode)
    {
        string keyName = GetKeyName(vkCode);
        Debug.Log(vkCode);
        Debug.Log(KeyCode.W);
        Debug.Log((int)KeyCode.W);

        //设置Text文字内容
        if (txt_NumberText)
        {
            txt_NumberText.text = (num++).ToString();
        }

        if(txt_vkText)
        {
            txt_vkText.text = keyName;
        }
    }

}

3.4 创建两个Text,一个记录点击键鼠次数,一个用于显示当前按下键鼠键位,创建空物体拖拽脚本,并将Text拖拽到脚本中


网站公告

今日签到

点亮在社区的每一天
去签到