通过 SendInput (Win32 API) 的键盘输入不起作用,硬件可以
Keyboard input via SendInput (Win32 API) doesnt work, hardware one does
我有一个任务,我需要在浏览器中显示的网络表单上进行一些鼠标点击,还需要进行一些键盘输入,例如用数字填充文本框或按顺序按下箭头以获得选择在组合框中。
Window 我有处理程序,也有点击坐标,它对我来说很好用(非常简单的功能):
extern "C" __declspec(dllexport) void __stdcall PutSingleClick(unsigned hwnd, int x, int y)
{
SendMessage(((HWND) hwnd), WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
SendMessage(((HWND) hwnd), WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x, y));
}
我尝试发送键盘输入时出现问题,例如通过调用:
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.time = 0;
ip.ki.wVk = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wScan = VK_DOWN;
for(int i = 0; i < times; i++)
{
ip.ki.dwFlags = KEYEVENTF_SCANCODE;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
ip.ki.dwFlags = KEYEVENTF_SCANCODE;
ip.ki.wScan = VK_RETURN;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
调用此函数后什么也没做,只有输入缓冲区中保留了奇怪的字符(在我的例子中是“´”[akcent,死字符])。
当我试图捕捉 Spy++ 发生的事情时,鼠标事件(点击)被正确侦测(当手动和程序生成时),但键盘事件不是——无论是程序还是手动。
虽然我尝试实用程序屏幕键盘(Windows 的公共部分),但它与硬件键盘一样好用(输入数字,更改选择的值....),但没有生成任何消息.
知道如何模拟硬件击键并在我需要的地方放置序列吗?
非常感谢。
VK_DOWN
和VK_RETURN
是虚拟键,不是扫码。因此,当调用 SendInput()
时,使用 ip.ki.wVk
字段而不是 ip.ki.wScan
字段,并去掉 KEYEVENTF_SCANCODE
标志:
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
INPUT ip = {0};
ip.type = INPUT_KEYBOARD;
ip.ki.wVk = VK_DOWN;
for(int i = 0; i < times; i++)
{
ip.ki.dwFlags = 0;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
ip.ki.dwFlags = 0;
ip.ki.wVk = VK_RETURN;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
但是,您不应该像这样调用 SendInput()
来单独发送多个输入事件。它违背了使用 SendInput()
与 keybd_event()
的目的,但有 none 的好处。相反,您应该使用数组在对 SendInput()
的一次调用中一次发送所有事件,例如:
#include <vector>
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
INPUT ip = {0};
ip.type = INPUT_KEYBOARD;
ip.ki.wVk = VK_DOWN;
std::vector<INPUT> ips;
ips.reserve((times*2)+2);
for(int i = 0; i < times; i++)
{
ip.ki.dwFlags = 0;
ips.push_back(ip);
ip.ki.dwFlags = KEYEVENTF_KEYUP;
ips.push_back(ip);
}
ip.ki.dwFlags = 0;
ip.ki.wVk = VK_RETURN;
ips.push_back(ip);
ip.ki.dwFlags = KEYEVENTF_KEYUP;
ips.push_back(ip);
SendInput(ips.size(), &ips[0], sizeof(INPUT));
}
我有一个任务,我需要在浏览器中显示的网络表单上进行一些鼠标点击,还需要进行一些键盘输入,例如用数字填充文本框或按顺序按下箭头以获得选择在组合框中。
Window 我有处理程序,也有点击坐标,它对我来说很好用(非常简单的功能):
extern "C" __declspec(dllexport) void __stdcall PutSingleClick(unsigned hwnd, int x, int y)
{
SendMessage(((HWND) hwnd), WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
SendMessage(((HWND) hwnd), WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x, y));
}
我尝试发送键盘输入时出现问题,例如通过调用:
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.time = 0;
ip.ki.wVk = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wScan = VK_DOWN;
for(int i = 0; i < times; i++)
{
ip.ki.dwFlags = KEYEVENTF_SCANCODE;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
ip.ki.dwFlags = KEYEVENTF_SCANCODE;
ip.ki.wScan = VK_RETURN;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
调用此函数后什么也没做,只有输入缓冲区中保留了奇怪的字符(在我的例子中是“´”[akcent,死字符])。
当我试图捕捉 Spy++ 发生的事情时,鼠标事件(点击)被正确侦测(当手动和程序生成时),但键盘事件不是——无论是程序还是手动。
虽然我尝试实用程序屏幕键盘(Windows 的公共部分),但它与硬件键盘一样好用(输入数字,更改选择的值....),但没有生成任何消息.
知道如何模拟硬件击键并在我需要的地方放置序列吗?
非常感谢。
VK_DOWN
和VK_RETURN
是虚拟键,不是扫码。因此,当调用 SendInput()
时,使用 ip.ki.wVk
字段而不是 ip.ki.wScan
字段,并去掉 KEYEVENTF_SCANCODE
标志:
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
INPUT ip = {0};
ip.type = INPUT_KEYBOARD;
ip.ki.wVk = VK_DOWN;
for(int i = 0; i < times; i++)
{
ip.ki.dwFlags = 0;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
ip.ki.dwFlags = 0;
ip.ki.wVk = VK_RETURN;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
但是,您不应该像这样调用 SendInput()
来单独发送多个输入事件。它违背了使用 SendInput()
与 keybd_event()
的目的,但有 none 的好处。相反,您应该使用数组在对 SendInput()
的一次调用中一次发送所有事件,例如:
#include <vector>
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
INPUT ip = {0};
ip.type = INPUT_KEYBOARD;
ip.ki.wVk = VK_DOWN;
std::vector<INPUT> ips;
ips.reserve((times*2)+2);
for(int i = 0; i < times; i++)
{
ip.ki.dwFlags = 0;
ips.push_back(ip);
ip.ki.dwFlags = KEYEVENTF_KEYUP;
ips.push_back(ip);
}
ip.ki.dwFlags = 0;
ip.ki.wVk = VK_RETURN;
ips.push_back(ip);
ip.ki.dwFlags = KEYEVENTF_KEYUP;
ips.push_back(ip);
SendInput(ips.size(), &ips[0], sizeof(INPUT));
}