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

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_EXPORTSextern "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拖拽到脚本中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97948.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97948.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习篇---MNIST:手写数字数据集

下面我将详细介绍使用 PyTorch 处理 MNIST 手写数字数据集的完整流程&#xff0c;包括数据加载、模型定义、训练和评估&#xff0c;并解释每一行代码的含义和注意事项。整个流程可以分为五个主要步骤&#xff1a;准备工作、数据加载与预处理、模型定义、模型训练和模型评估。# …

k8s集群搭建(二)-------- 集群搭建

安装 containerd 需要在集群内的每个节点上都安装容器运行时&#xff08;containerd runtime&#xff09;&#xff0c;这个软件是负责运行容器的软件。 1. 启动 ipv4 数据包转发 # 设置所需的 sysctl 参数&#xff0c;参数在重新启动后保持不变 cat <<EOF | sudo tee …

【Docker】P1 前言:容器化技术发展之路

目录容器发展之路物理服务器时代&#xff1a;一机一应用的局限虚拟化时代&#xff1a;突破与局限并存容器化时代&#xff1a;轻量级的革新技术演进的价值体现各位&#xff0c;欢迎来到容器化时代。 容器发展之路 现代业务的核心是应用程序&#xff08;Application&#xff09;…

WPF依赖属性和依赖属性的包装器:

依赖属性是WPF&#xff08;Windows Presentation Foundation&#xff09;中的一种特殊类型的属性&#xff0c;特别适用于内存使用优化和属性值继承。依赖属性的定义包括以下几个步骤&#xff1a; 使用 DependencyProperty.Register 方法注册依赖属性。 该方法需要四个参数&…

图生图算法

图生图算法研究细分&#xff1a;技术演进、应用与争议 1. 基于GAN的传统图生图方法 定义&#xff1a;利用生成对抗网络&#xff08;GAN&#xff09;将输入图像转换为目标域图像&#xff08;如语义图→照片、草图→彩图&#xff09;。关键发展与趋势&#xff1a; Pix2Pix&#…

Go 自建库的使用教程与测试

附加一个Go库的实现&#xff0c;相较于Python&#xff0c;Go的实现更较为日常&#xff0c;不需要额外增加setup.py类的文件去额外定义,计算和并发的性能更加。 1. 创建 Go 模块项目结构 首先创建完整的项目结构&#xff1a; gomathlib/ ├── go.mod ├── go.sum ├── cor…

What is a prototype network in few-shot learning?

A prototype network is a method used in few-shot learning to classify new data points when only a small number of labeled examples (the “shots”) are available per class. It works by creating a representative “prototype” for each class, which is typical…

Linux中用于线程/进程同步的核心函数——`sem_wait`函数

<摘要> sem_wait 是 POSIX 信号量操作函数&#xff0c;用于对信号量执行 P 操作&#xff08;等待、获取&#xff09;。它的核心功能是原子地将信号量的值减 1。如果信号量的值大于 0&#xff0c;则减 1 并立即返回&#xff1b;如果信号量的值为 0&#xff0c;则调用线程&…

25高教社杯数模国赛【B题超高质量思路+问题分析】

注&#xff1a;本内容由”数模加油站“ 原创出品&#xff0c;虽无偿分享&#xff0c;但创作不易。 欢迎参考teach&#xff0c;但请勿抄袭、盗卖或商用。 B 题 碳化硅外延层厚度的确定碳化硅作为一种新兴的第三代半导体材料&#xff0c;以其优越的综合性能表现正在受到越来越多…

【Linux篇章】再续传输层协议UDP :从低可靠到极速传输的协议重生之路,揭秘无连接通信的二次进化密码!

&#x1f4cc;本篇摘要&#xff1a; 本篇将承接上次的UDP系列网络编程&#xff0c;来深入认识下UDP协议的结构&#xff0c;特性&#xff0c;底层原理&#xff0c;注意事项及应用场景&#xff01; &#x1f3e0;欢迎拜访&#x1f3e0;&#xff1a;点击进入博主主页 &#x1f4c…

《A Study of Probabilistic Password Models》(IEEE SP 2014)——论文阅读

提出更高效的密码评估工具&#xff0c;将统计语言建模技术引入密码建模&#xff0c;系统评估各类概率密码模型性能&#xff0c;打破PCFGw的 “最优模型” 认知。一、研究背景当前研究存在两大关键问题&#xff1a;一是主流的 “猜测数图” 计算成本极高&#xff0c;且难以覆盖强…

校园外卖点餐系统(代码+数据库+LW)

摘要 随着校园生活节奏的加快&#xff0c;学生对外卖的需求日益增长。然而&#xff0c;传统的外卖服务存在诸多不便&#xff0c;如配送时间长、菜品选择有限、信息更新不及时等。为解决这些问题&#xff0c;本研究开发了一款校园外卖点餐系统&#xff0c;采用前端 Vue、后端 S…

友思特案例 | 食品行业视觉检测案例集锦(三)

食品制造质量检测对保障消费者安全和产品质量稳定至关重要&#xff0c;覆盖原材料至成品全阶段&#xff0c;含过程中检测与成品包装检测。近年人工智能深度学习及自动化系统正日益融入食品生产。本篇文章将介绍案例三&#xff1a;友思特Neuro-T深度学习平台进行面饼质量检测。在…

SQLynx 3.7 发布:数据库管理工具的性能与交互双重进化

目录 &#x1f511; 核心功能更新 1. 单页百万级数据展示 2. 更安全的数据更新与删除机制 3. 更智能的 SQL 代码提示 4. 新增物化视图与外表支持 5. 数据库搜索与过滤功能重构 ⚡ 总结与思考 在大数据与云原生应用快速发展的今天&#xff0c;数据库管理工具不仅要“能用…

10G网速不是梦!5G-A如何“榨干”毫米波,跑出比5G快10倍的速度?

5G-A&#xff08;5G-Advanced&#xff09;网络技术已经在中国福建省厦门市软件园成功实现万兆&#xff08;10Gbps&#xff09;速率验证&#xff0c;标志着我国正式进入5G增强版商用阶段。这一突破性成果不仅验证了5G-A技术的可行性&#xff0c;也为6G网络的发展奠定了坚实基础。…

Linux笔记---UDP套接字实战:简易聊天室

1. 项目需求分析 我们要设计的是一个简单的匿名聊天室&#xff0c;用户的客户端要求用户输入自己的昵称之后即可在一个公共的群聊当中聊天。 为了简单起见&#xff0c;我们设计用户在终端当中与客户端交互&#xff0c;而在一个文件当中显式群聊信息&#xff1a; 当用户输入的…

RTP打包与解包全解析:从RFC规范到跨平台轻量级RTSP服务和低延迟RTSP播放器实现

引言 在实时音视频系统中&#xff0c;RTSP&#xff08;Real-Time Streaming Protocol&#xff09;负责会话与控制&#xff0c;而 RTP&#xff08;Real-time Transport Protocol&#xff09;负责媒体数据承载。开发者在实现跨平台、低延迟的 RTSP 播放器或轻量级 RTSP 服务时&a…

Ubuntu 用户和用户组

一、 Linux 用户linux 是一个多用户操作系统&#xff0c;不同的用户拥有不同的权限&#xff0c;可以查看和操作不同的文件。 Ubuntu 有三种用户1、初次创建的用户2、root 用户---上帝3、普通用户初次创建的用户权限比普通用户要多&#xff0c;但是没有 root 用户多。Linux 用户…

FastGPT社区版大语言模型知识库、Agent开源项目推荐

​ FastGPT 项目说明 项目概述 FastGPT 是一个基于大语言模型&#xff08;LLM&#xff09;的知识库问答系统&#xff0c;提供开箱即用的数据处理和模型调用能力&#xff0c;支持通过可视化工作流编排实现复杂问答场景。 技术架构 前端: Next.js TypeScript Chakra UI 后…

jsencrypt公钥分段加密,支持后端解密

前端使用jsencryp实现分段加密。 解决长文本RSA加密报错问题。 支持文本包含中文。 支持后端解密。前端加密代码&#xff1a; // import { JSEncrypt } from jsencrypt const JSEncrypt require(jsencrypt) /*** 使用 JSEncrypt 实现分段 RSA 加密&#xff08;正确处理中文字符…