我想使用SendInput()函数自动按某些键。
我的代码:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <Windows.h>
using std::cin;
using std::cout;
using std::string;
void presskeys(string s){
INPUT ip;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
HKL kbl = GetKeyboardLayout(0);
for (unsigned int i = 0; i < s.length(); ++i) {
ip.type = INPUT_KEYBOARD;
char c = s[i];
int vk = VkKeyScanEx((WCHAR)c, kbl);
ip.ki.wVk = vk;
SendInput(1, &ip, sizeof(ip));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(ip));
}
}
int main()
{
cout << "Enter a string!\n";
string str;
cin >> str;
Sleep(5000);
presskeys(str);
cout << "Done!\n";
return 0;
}
我启动程序并输入一个字符串,但不会发生任何事情。它出了什么问题?
答案 0 :(得分:2)
与Barmak说的一样,您正在以不正确的方式将ANSI和UNICODE混合在一起,并且您没有正确管理输入标志。
发送字符串字符时,最好通过KEYEVENTF_UNICODE
标志发送UTF-16代码单元,而不是使用扫描代码或虚拟密钥。
您还应该为整个字符串调用SendInput()
一次,其中包含多个INPUT
结构,以便所有字符作为一个单元一起发送,而不是被用户或其他应用程序/线程同时生成的其他输入事件中断或混合。
请参阅my answer至Sending Two or more chars using SendInput。
例如:
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
void presskeys(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));
}
int main()
{
std::wcout << L"Enter a string and press enter:\n";
std::wstring str;
if (std::getline(std::wcin, str))
{
presskeys(str);
std::wcout << L"Done!\n";
}
return 0;
}
答案 1 :(得分:0)
您正在使用ANSI字符串,因此请使用VkKeyScanExA
,或切换到std::wstring
。但是不要将ANSI与UNICODE混合使用,也不要使用强制转换来隐藏编译器警告。
您必须将ip.ki.dwFlags
重置为零以指示按键关闭。然后将其设置为KEYEVENTF_KEYUP
。
你还必须检查caplock和shift等的关键状态。以这种方式使用SendInput
是没有意义的,第一个参数是允许一次发送多个输入。您也可以使用keybd_event
void presskeys(string s)
{
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
HKL kbl = GetKeyboardLayout(0);
for (unsigned int i = 0; i < s.length(); ++i)
{
char c = s[i];
ip.ki.wVk = VkKeyScanExA(c, kbl); //<== don't mix ANSI with UNICODE
ip.ki.dwFlags = 0; //<= Add this to indicate key-down
SendInput(1, &ip, sizeof(ip));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(ip));
}
}