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;
}
}
}