鸡胸肉键盘?看我复刻之.....C#软件大杂烩(1.4)串口映射键盘
今天在抖音冲浪,突然刷到了某佬用鸡胸肉当键盘。

OK,这东西熟悉呀,好酷。
我在家疯狂寻找。

原理阐述
由于人体在接触ESP32的IO时会导致电容值发生变化,ESP32总共有十个可以直接读取电容的IO,我们可以利用电容量变化来判断我们是否按下。

在Arduino IDE中利用以下函数读取触摸传感器
for(;;)
{
Serial.print("A:");
Serial.println(touchRead(4));
delay(10);
}
用上述代码,我们进行测试。

可以发现,在空置的时候,触摸传感器的值在80作用,当我们触摸IO(我拉了根杜邦线)的时候,电容的值会降到10+。变化非常明显。
知道这个原理,我们加点判断逻辑,即可实现触摸的检测。
接下来写一个上位机程序
using System.Management;
using System.Runtime.InteropServices;
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
struct INPUT
{
public int type;
public InputUnion u;
}
[StructLayout(LayoutKind.Explicit)]
struct InputUnion
{
[FieldOffset(0)]
public MOUSEINPUT mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
struct HARDWAREINPUT
{
public uint uMsg;
public ushort wParamL;
public ushort wParamH;
}
const int INPUT_KEYBOARD = 1;
const uint KEYEVENTF_KEYUP = 0x0002;
public static void SendKey(ushort key, bool keyUp)
{
INPUT[] inputs = new INPUT[]
{
new INPUT
{
type = INPUT_KEYBOARD,
u = new InputUnion
{
ki = new KEYBDINPUT
{
wVk = key,
wScan = 0,
dwFlags = keyUp ? KEYEVENTF_KEYUP : 0,
time = 0,
dwExtraInfo = IntPtr.Zero
}
}
}
};
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
}
char boolc;
private void SendKeysToApplication(string input)
{
foreach (char c in input)
{
if(c!='T')
{
SendKey(c, true);
boolc = c;
}
else
{
SendKey(boolc, false);
}
}
}
我们调用系统API将我们接收到的文本转化为键盘硬件输出(有些游戏会把模拟键盘视作外挂(英雄联盟我试了不行))并且在串口接收的部分调用这个函数。
System.Management 用于管理和操作Windows管理信息。
System.Runtime.InteropServices 用于在托管代码和非托管代码之间进行工作,特别是用于调用Windows API。
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
这是 SendInput 函数的声明,它来自user32.dll(一个Windows系统库),用于插入键盘或鼠标输入事件到Windows的消息队列。
SetLastError = true 表示如果函数调用失败,可以使用 Marshal.GetLastWin32Error() 来获取错误代码。
结构体定义
代码中定义了几个结构体,它们对应于 SendInput 函数所需的参数。
struct INPUT
{
public int type;
public InputUnion u;
}
type 表示输入类型,例如键盘输入(INPUT_KEYBOARD)。
u 是一个联合体,可以表示鼠标、键盘或硬件输入。
[StructLayout(LayoutKind.Explicit)]
struct InputUnion
{
[FieldOffset(0)]
public MOUSEINPUT mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
一个具有显式布局的结构体,其成员共享相同的内存位置(所有成员的 FieldOffset 都是0)。这意味着 mi、ki 和 hi 实际上是互相重叠的,这个结构体在任何时候只能表示其中一种输入。MOUSEINPUT, KEYBDINPUT, HARDWAREINPUT 结构体这些结构体包含了模拟鼠标、键盘和硬件输入所需的具体信息。
- 最后SendKey中,第一个参数是字符,第二个参数是模拟按下还是释放



登录 或 注册 后才可以进行评论哦!
还没有评论,抢个沙发!