使用SendInput发送两个或多个字符
Sending Two or more chars using SendInput
要发送一个字符,我们可以使用SendInput。如何使用它发送多个字符?
我尝试了这个代码,但它没有发送任何东西:
INPUT in;
in.type=INPUT_KEYBOARD;
in.ki.wScan=0;
in.ki.time=0;
in.ki.dwExtraInfo=0;
in.ki.wVk=0x53+0x54;
SendInput(2,&in,sizeof(INPUT));
那么,什么是正确的方法呢?
SendInput()
的第一个参数指定要传入的INPUT
结构的数量。您只传入1,但告诉SendInput()
您要传入2。
不能在单个INPUT
中指定两个独立的虚拟密钥。您需要声明一个由多个INPUT
s组成的数组,每个虚拟键有2个INPUT
s——一个用于keydown事件,一个用于key up事件。因此,在您的示例中,您实际上需要4个INPUT
来发送2个虚拟密钥,如@user4581301的回答所示。
现在,关于KEYEVENTF_UNICODE
,您不使用虚拟键,而是使用实际的Unicode代码点,它们是使用UTF-16代码单元指定的,每个INPUT
一个。因此,这意味着,如果要发送需要UTF-16代理项对的Unicode代码点,则需要两组向下/向上的INPUT
s,一组用于高代理项,另一组用于低代理项。这个警告是SendInput()
文档中提到的NOT,但vScan
字段是一个16位WORD
,并且KEYEVENTF_UNICODE
事件生成WM_CHAR
消息,该消息将UTF-16代理代码单元作为单独的消息传递。
因此,要使用KEYEVENTF_UNICODE
发送一串Unicode字符,可以执行以下操作:
#include <vector>
#include <string>
void SendInputString(const std::wstring &str)
{
int len = str.length();
if (len == 0) return;
std::vector<INPUT> in(len*2);
ZeroMemory(&in[0], in.size()*sizeof(INPUT));
int i = 0, idx = 0;
while (i < len)
{
WORD ch = (WORD) str[i++];
if ((ch < 0xD800) || (ch > 0xDFFF))
{
in[idx].type = INPUT_KEYBOARD;
in[idx].ki.wScan = ch;
in[idx].ki.dwFlags = KEYEVENTF_UNICODE;
++idx;
in[idx] = in[idx-1];
in[idx].ki.dwFlags |= KEYEVENTF_KEYUP;
++idx;
}
else
{
in[idx].type = INPUT_KEYBOARD;
in[idx].ki.wScan = ch;
in[idx].ki.dwFlags = KEYEVENTF_UNICODE;
++idx;
in[idx].type = INPUT_KEYBOARD;
in[idx].ki.wScan = (WORD) str[i++];
in[idx].ki.dwFlags = KEYEVENTF_UNICODE;
++idx;
in[idx] = in[idx-2];
in[idx].ki.dwFlags |= KEYEVENTF_KEYUP;
++idx;
in[idx] = in[idx-2];
in[idx].ki.dwFlags |= KEYEVENTF_KEYUP;
++idx;
}
}
SendInput(in.size(), &in[0], sizeof(INPUT));
}
如果我说得对,你需要更多类似以下内容的东西:
INPUT in[4] = {0}; // four inputs
// first input 0x53
in[0].type=INPUT_KEYBOARD;
in[0].ki.wScan=0;
in[0].ki.dwFlags=0;
in[0].ki.time=0;
in[0].ki.dwExtraInfo=0;
in[0].ki.wVk=0x53;
in[1] = in[0];
in[1].ki.dwFlags |= KEYEVENTF_KEYUP;
// second input 0x54
in[2].type=INPUT_KEYBOARD;
in[2].ki.wScan=0;
in[2].ki.dwFlags=0;
in[2].ki.time=0;
in[2].ki.dwExtraInfo=0;
in[2].ki.wVk=0x54;
in[3] = in[2];
in[3].ki.dwFlags |= KEYEVENTF_KEYUP;
SendInput(4,in,sizeof(INPUT));
可能希望将设置INPUT结构的繁重工作打包为一个函数,以减少重复。
其他答案似乎在DirectX游戏中不起作用。我在TrackMania Nations测试了以下内容,它运行正常:(记事本等也运行(
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <string>
void press_some_keys (std::string str) {
INPUT input[2 * (int)str.size()] = {0};
int cnt = 0;
for (char ch: str) {
input[cnt].type = INPUT_KEYBOARD;
input[cnt].ki.dwFlags = KEYEVENTF_SCANCODE;
input[cnt].ki.wScan = MapVirtualKey(LOBYTE(VkKeyScan(ch)), 0);
cnt++;
input[cnt] = input[cnt - 1];
cnt++;
}
SendInput(2 * (int)str.size(), input, sizeof(INPUT));
Sleep(10);
for (cnt = 1; cnt < 2 * (int)str.size(); cnt += 2)
input[cnt].ki.dwFlags |= KEYEVENTF_KEYUP;
SendInput(2 * (int)str.size(), input, sizeof(INPUT));
}
我只测试了小写字母字符(没有箭头或其他(,但这对我来说已经足够了
让它工作起来很痛苦,因为我发现最接近的是Youtube视频中的一个点击功能:-(
- 如何读取单个字符并在输入两个字符序列时输出? 使用 while 循环和C++
- 在函数中连接两个字符,并在 C++ 中返回输出
- 舍入 QDecDouble 值,精度最多为两个字符
- 计算两个字符序列
- 在c++中连接两个字符
- 有没有办法我可以从 istringstream 中读取两个字符
- 如何查看两个字符变量是否相等
- 使用位于 C 字符串中的两个字符*获取子字符串
- 比较两个字符的问题
- 如何修复密码条目,它一次输入两个字符
- 字符串构造函数将两个字符* 放入另一个 std::string 在 C++14 中有效,但不适用于 C++17
- 将两个字符数组相互添加
- 在 c++ 中添加两个字符
- 如何删除QString的前两个字符
- 如何使用两个字符来控制 C++ 程序的流程
- 如何将两个字符或字符串数组附加到一个数组中
- 如何从两个字符之间的文件中提取整数
- 删除两个字符之间的文本
- std::setw() 将特殊字符视为两个字符
- 比较两个字符*是否相等