很多小盆友表示买不起机械键盘,甚至买不起机械手感键盘,一直在用笔记本自带的键盘。那么如何改造成机械键盘?废话不多说,上代码。
1.首先写一个全局监听键盘的类,主要是利用勾子实现。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;namespace KeyboardMusic
{class KeyBoardHook{//需要绑定的事件public event KeyEventHandler KeyUpEvent;public event KeyEventHandler KeyDownEvent;public event KeyPressEventHandler KeyPressEvent;public delegate int HookProc(int nCode, int wParam, IntPtr lParam);static int hKeyboardHook = 0; //声明键盘钩子处理的初始值public const int WH_KEYBOARD_LL = 13;//全局键盘监听鼠标消息为13HookProc KeyboardHookProcedure;[StructLayout(LayoutKind.Sequential)]public class KeyboardHookStruct{public int vkCode;  public int scanCode;public int flags; public int time;public int dwExtraInfo;}//安装钩子[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]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", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);// 取得当前线程编号[DllImport("kernel32.dll")]static extern int GetCurrentThreadId();//防止钩子失效[DllImport("kernel32.dll")]public static extern IntPtr GetModuleHandle(string name);public void Start(){// 安装键盘钩子if (hKeyboardHook == 0){KeyboardHookProcedure = new HookProc(KeyboardHookProc);hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName), 0);if (hKeyboardHook == 0){Stop();throw new Exception("安装失败");}}}public void Stop(){bool retKeyboard = true;if (hKeyboardHook != 0){retKeyboard = UnhookWindowsHookEx(hKeyboardHook);hKeyboardHook = 0;}if (!(retKeyboard)) throw new Exception("卸载钩子失败!");}//ToAscii职能的转换指定的虚拟键码和键盘状态的相应字符或字符[DllImport("user32")]public static extern int ToAscii(int uVirtKey, //[in] 指定虚拟关键代码进行翻译。int uScanCode, // [in] 指定的硬件扫描码的关键须翻译成英文。高阶位的这个值设定的关键,如果是(不压)byte[] lpbKeyState, // [in] 指针,以256字节数组,包含当前键盘的状态。每个元素(字节)的数组包含状态的一个关键。如果高阶位的字节是一套,关键是下跌(按下)。在低比特,如果设置表明,关键是对切换。在此功能,只有肘位的CAPS LOCK键是相关的。在切换状态的NUM个锁和滚动锁定键被忽略。byte[] lpwTransKey, // [out] 指针的缓冲区收到翻译字符或字符。int fuState); // [in] Specifies whether a menu is active. This parameter must be 1 if a menu is active, or 0 otherwise.//获取按键的状态[DllImport("user32")]public static extern int GetKeyboardState(byte[] pbKeyState);[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]private static extern short GetKeyState(int vKey);private const int WM_KEYDOWN = 0x100;//KEYDOWNprivate const int WM_KEYUP = 0x101;//KEYUPprivate const int WM_SYSKEYDOWN = 0x104;//SYSKEYDOWNprivate const int WM_SYSKEYUP = 0x105;//SYSKEYUPprivate int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam){// 侦听键盘事件if ((nCode >= 0) && (KeyDownEvent != null || KeyUpEvent != null || KeyPressEvent != null)){KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));// 键盘按下if (KeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)){Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;KeyEventArgs e = new KeyEventArgs(keyData);KeyDownEvent(this, e);}//键盘按着if (KeyPressEvent != null && wParam == WM_KEYDOWN){byte[] keyState = new byte[256];GetKeyboardState(keyState);byte[] inBuffer = new byte[2];if (ToAscii(MyKeyboardHookStruct.vkCode, MyKeyboardHookStruct.scanCode, keyState, inBuffer, MyKeyboardHookStruct.flags) == 1){KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]);KeyPressEvent(this, e);}}// 键盘抬起if (KeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)){Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;KeyEventArgs e = new KeyEventArgs(keyData);KeyUpEvent(this, e);}}return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);}~KeyBoardHook(){Stop();}}
}

2.在form_load事件中调用这个类安装钩子,并且注册事件

KeyBoardHook k_hook = new KeyBoardHook();
k_hook.KeyDownEvent += new KeyEventHandler(hook_KeyDown);//钩住键按下
k_hook.KeyUpEvent += new KeyEventHandler(hook_KeyUp);//钩住键按下
k_hook.Start();//安装键盘钩子

3.自己想办法搞一个机械键盘的音效去,注意必须是两个wav文件,一个是按下,一个是抬起

private void hook_KeyDown(object sender, KeyEventArgs e)
{//单独键盘按键//string keyCode = e.KeyCode.ToString();string m = Application.StartupPath.Replace(@"\", @"/") + @"/wav/mechanicalKeyboard_down.wav";using (System.Media.SoundPlayer sndPlayer = new System.Media.SoundPlayer(m)){sndPlayer.Play();}
}
private void hook_KeyUp(object sender, KeyEventArgs e)
{string m = Application.StartupPath.Replace(@"\", @"/") + @"/wav/mechanicalKeyboard_up.wav";using (System.Media.SoundPlayer sndPlayer = new System.Media.SoundPlayer(m)){sndPlayer.Play();}
}

4.这样就可以实现机械耳感键盘啦,如果你有兴趣,可以通过e.KeyCode获取你按下的具体数值按键,进而设置不同的音效,本人就搞了一个,他会说出你按下的键,像极了计算器,非常沙雕。。。

如果喜欢就点个赞哇!!!

C#打造机械耳感键盘(全局监听键盘并设置音效)相关推荐

  1. C# 全局监听键盘源代码

    一.开发环境及语言: win10 win11 VS2019的C#语言 二.解决问题 当C#监听页面窗口,不在第一页面或者页面窗口不在最前方时,也能监听到键盘的任何一个键. 三.效果展示: C# 全局监 ...

  2. Angular 全局监听键盘事件

    技术点:使用EventManager 根模块中不要引用,组件模块中引用 import { EventManager } from '@angular/platform-browser'; 组件cons ...

  3. MFC 全局钩子dll注入监听键盘消息

    MFC自带的键盘监听功能只有焦点在MFC程序界面时才能监听键盘消息,要想在MFC程序界面外监听键盘消息,可以通过DLL注入使用全局钩子来监听.首先,通过Visual Studio生成全局钩子的动态库, ...

  4. java键盘监听事件代码_JavaScript监听键盘事件代码实现

    在写网页的时候,常常需要监听键盘事件,让我们来看看如何实现吧. 监听方式 键盘事件往往是全局监听,设监听的函数为keyboard(). keyup事件类型.该类型触发条件为按键按下去并松开. //长按 ...

  5. 用键盘全局钩子[Hook]监视多进程键盘操作

    用键盘全局钩子[Hook]监视多进程键盘操作 闲来无事,在WIN2K下用BCB5做了个键盘挂钩小程序,监视全局按键情况.Hook安放和回调函数放在一个单独DLL中,DLL原码如下: //------- ...

  6. 修改某个UITextField的键盘的返回键类型以及监听键盘的高度变化,取到键盘动画退出弹出的时间,一起随着键盘顶出来或者压下去,...

    1.修改某个UITextField的键盘的返回键类型: [_bottomTextView setReturnKeyType:UIReturnKeyDone]; 1.1.textFied点击return ...

  7. html键盘事件监听,react怎样监听键盘事件

    react监听键盘事件的方法:React中有监听键盘按下事件onKeyUp或者onKeyDown属性(以下用onKeyUp),值为自定义方法keyUp,即onKeyUp={this.keyUp}. 通 ...

  8. [Java][详解]使用jintellitype实现键盘全局监听

    [下载jintellitype] 首先要下载jintellitype-1.3.9,这里提供下载地址 [jintellitype-百度网盘下载] 链接: https://pan.baidu.com/s/ ...

  9. 如何在VR全景中嵌入AI数字人功能?打造云端体验感

    互联网产品的更新迭代是很快的,众多行业都会不断的上新产品,不久前我们推出了AI数字人讲解功能,那么如何在VR全景作品中嵌入这种功能呢?其实这些功能都是市场发展的需求,毕竟现在元宇宙的概念爆火也在无形之 ...

最新文章

  1. 转换 Byte 数组到 ... - 回复 高群 的问题
  2. Silverlight开发历程—(输入事件和非输入事件)
  3. Happy 牛 Year!牛年dotnet云原生技术趋势
  4. 设计模式(第十七式:迭代器模式)
  5. Windows PowerShell 2.0创建调用脚本文件
  6. U分布、T分布、z分位数
  7. java母类_java关键字分类详解
  8. 2020我们一起“只争朝夕,不负韶华”
  9. [NOI2002]贪吃的九头龙(树形dp)
  10. SSH连接服务器断开
  11. ThinkAdmin列目录/任意文件读取(CVE-2020-25540 )漏洞复现及环境搭建
  12. sklearn机器学习之svm案例(预测明天是否会下雨)
  13. 达梦误删除表空间文件恢复
  14. 量子计算到底是什么?
  15. 大整数运算-大数的存储与运算
  16. oCPC实践录 | 糟糕,广告主成本超了!
  17. JavaScript贷款计算器
  18. 大学计算机基础报告总结,windows7实验报告总结.docx
  19. 【MySQL】存储过程与存储函数
  20. IT公司、软件公司资质(转)

热门文章

  1. unable to locate解决方法
  2. 尚硅谷MySQL高级JAVA版
  3. mysql 字符串截取,拼接
  4. 如何在cmd命令行窗口打开QQ
  5. GME轧空事件的战后处置和思考
  6. ModuleNotFoundError: No module named ‘lap‘ 已解决
  7. 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第10章 分析句子的意思
  8. jqGrid subGrid配置 如何首次加载动态展开所有的子表格
  9. 一只喵的西行记-10 哲学家H+计划
  10. K8S集群中Pod与Pod之间网络故障排查思路