您的位置:首页 > 编程语言 > C#

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

2020-07-14 06:11 645 查看

很多小盆友表示买不起机械键盘,甚至买不起机械手感键盘,一直在用笔记本自带的键盘。那么如何改造成机械键盘?废话不多说,上代码。
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;//全局键盘监听鼠标消息为13
HookProc 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;//KEYDOWN
private const int WM_KEYUP = 0x101;//KEYUP
private const int WM_SYSKEYDOWN = 0x104;//SYSKEYDOWN
private const int WM_SYSKEYUP = 0x105;//SYSKEYUP

private 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获取你按下的具体数值按键,进而设置不同的音效,本人就搞了一个,他会说出你按下的键,像极了计算器,非常沙雕。。。

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: