由于keybd_event() 已被SendInput() 取代,我建议您改用它。
使用SendInput(),您可以发送多个INPUT 结构。您可以发送鼠标输入、键盘输入和硬件输入。我将展示如何发送键盘输入。
可以使用扫描码或 Unicode 字符发送键盘输入。我将使用 Unicode。为你不知道的东西找到 Unicode 字符通常很简单:https://www.google.com/search?q=unicode+exclamation+mark,你会得到答案,比如 U+0021 代表 !,它可以在 C++ 的 Unicode 字符串中编码为 \u0021 .
我将从继承INPUT 结构开始,以使其更易于实例化:
#include <Windows.h>
#include <iostream>
#include <stdexcept>
#include <vector>
struct mINPUT : INPUT {
mINPUT() : INPUT{} {} // make sure it's clean if default constructed.
// this constructor prepares the structure for different kinds of input:
mINPUT(DWORD type) : INPUT{type} {
switch (type) {
case INPUT_MOUSE:
// use mi.
break;
case INPUT_KEYBOARD:
// use ki.
ki.dwFlags = KEYEVENTF_UNICODE; // we'll use unicode
break;
case INPUT_HARDWARE:
// use hi.
break;
}
}
};
// helper functions to create `mINPUT` structures from Unicode values:
mINPUT key_down(char16_t unicode_char) {
mINPUT rv{INPUT_KEYBOARD};
rv.ki.wScan = unicode_char;
return rv;
}
mINPUT key_up(char16_t unicode_char) {
mINPUT rv{INPUT_KEYBOARD};
rv.ki.dwFlags |= KEYEVENTF_KEYUP;
rv.ki.wScan = unicode_char;
return rv;
}
// Helper functions to check UTF16 surrogate ranges
bool is_surrogate(char16_t code_unit) {
return code_unit >= 0xD800 && code_unit <= 0xDFFF;
}
bool is_high_surrogate(char16_t code_unit) {
return code_unit >= 0xD800 && code_unit <= 0xDBFF;
}
bool is_low_surrogate(char16_t code_unit) {
return code_unit >= 0xDC00 && code_unit <= 0xDFFF;
}
// A helper structure to prepare a sequence of events
struct Inputs {
UINT cInputs() const { return static_cast<UINT>(inputs.size()); }
LPINPUT pInputs() { return inputs.data(); }
int cbSize() const { return static_cast<int>(sizeof(INPUT)); }
// A helper function to add down+up events for a string:
void add_string(const char16_t* str) {
while (*str) {
char16_t ch = *str++;
if (is_surrogate(ch)) {
char16_t first = ch;
char16_t second = *str++;
if (!is_high_surrogate(first) || !is_low_surrogate(second))
throw std::runtime_error("Broken UTF16 surrogate pair");
inputs.push_back(key_down(first));
inputs.push_back(key_down(second));
inputs.push_back(key_up(first));
inputs.push_back(key_up(second));
} else {
inputs.push_back(key_down(ch));
inputs.push_back(key_up(ch));
}
}
}
UINT Send() { // Send the stored events
return SendInput(cInputs(), pInputs(), cbSize());
}
std::vector<mINPUT> inputs;
};
int main() {
std::cout << "Switch to Notepad or some other app taking input" << std::endl;
Sleep(5000); // in 5 seconds, you should see the input
Inputs x; // Create an event container
// Add events for a full string including exclamation marks in two
// different formats:
x.add_string(u"Hello world!!! or \u0021\u0021\u0021 ");
x.add_string(u"This is something with surrogate pairs: ? ?");
// Send the events:
UINT rv = x.Send();
std::cout << "Sent " << rv << " events\n";
}
如果一切按计划进行,它将发送134 事件,并且您应该会看到感叹号和其他字符出现在您激活的任何应用程序中,如果它能够接收键盘输入并显示结果,例如记事本或可视化Studio - 所以要小心放置光标的位置。