如果我想使用像 0xE0 0x1D (用于右 CTRL)这样的扩展扫描代码来模拟按键,我将如何在 C 中模拟这样的按键?我试过SendInput
用两个INPUT
结构调用,但只有左 CTRL 键被“按下”。对于具有“双胞胎”(Shift 和 Alt)的其他键,也会发生同样的情况。
其次,如何为“扩展”键引发 keyup 事件?
该KEYBDINPUT
结构有一个KEYEVENTF_EXTENDEDKEY
标志来0xE0
为您处理字节:
如果指定,则扫描代码前面有一个值为 0xE0 (224) 的前缀字节。
尝试这样的事情:
INPUT inputs[2];
ZeroMemory(inputs, sizeof(inputs));
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wScan = 0x1D;
inputs[0].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_EXTENDEDKEY;
CopyMemory(&inputs[1], &inputs[0], sizeof(INPUT));
inputs[1].ki.dwFlags |= KEYEVENTF_KEYUP;
SendInput(2, inputs, sizeof(INPUT));
但是,我建议使用虚拟键而不是扫描码:
INPUT inputs[2];
ZeroMemory(inputs, sizeof(inputs));
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = VK_CONTROL;
inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
CopyMemory(&inputs[1], &inputs[0], sizeof(INPUT));
inputs[1].ki.dwFlags |= KEYEVENTF_KEYUP;
SendInput(2, inputs, sizeof(INPUT));
但是,如果您绝对需要扫描码,至少看看MapVirtualKey()
将虚拟键转换为扫描码:
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wScan = MapVirtualKey(VK_RCONTROL, MAPVK_VK_TO_VSC);
inputs[0].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_EXTENDEDKEY;
您没有指定将密钥发送到同一个应用程序还是另一个应用程序。使用 SendInput,我们无法指定键的去向。我们必须以某种方式确保窗口处于活动状态并且焦点设置正确。请注意,SendInput 将发送 WM_KEYDOWN 或 WM_KEYUP 消息。如果您直接使用 SendMesage 发送 WM_KEYDOWN 和 WM_KEYUP 消息,您将拥有更大的灵活性。您指定要发送到的窗口的窗口句柄。窗口句柄用于文本框或接受文本的控件,而不是文本框或其他控件所在的窗口。
这是确定要在 SendMessage 中使用的确切参数的方法。请注意,SendInput 将产生一个 SendMessage。
在 Visual Studio 中,单击工具菜单。您将看到“Spy++”和“Spy++ x64”。我不确定我们何时需要其中一种,但如果其中一种不起作用,请尝试另一种。在 Spy++ 中,点击 Messages 菜单,然后点击“Logging Options...”。在右上角区域单击查找器工具并拖动到一个窗口。释放鼠标后,单击“消息”选项卡。然后单击“全部清除”,然后选中“键盘”复选框。请注意,Messages 菜单还具有用于启动和停止日志记录的命令,但我认为它默认是打开的。转到所选窗口并键入要尝试的键。然后查看 Spy++ 中记录的消息。您将看到发送到/从窗口发送的所有消息。我通常会在拥有所需的一切后立即停止记录,根据为记录选择的消息,记录的消息可能过多而无用。如果您只记录键盘消息,那么您将不会记录太多消息。
对我来说,扩展字段是右 Ctrl 的 1 和左 Ctrl 的 0。