c++ - SendInput() 不能正确管理 Alt 代码
c++ - SendInput() doesn't manage Alt codes properly
在我正在开发的程序中,我必须模拟击键,为此我使用 SendInput()
方法,将包含作为击键一部分的输入的向量作为参数传递。我当前的代码似乎适用于我正在测试的所有组合,但 Alt 代码除外。
这是我目前所做的:
// Press ALT
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_LMENU;
input.ki.wScan = 0;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Press NumPad2
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD2;
input.ki.wScan = 0;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Release NumPad2
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD2;
input.ki.wScan = 0;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Press NumPad1
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD1;
input.ki.wScan = 0;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Release NumPad1
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD1;
input.ki.wScan = 0;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Press NumPad2
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD2;
input.ki.wScan = 0;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Release NumPad2
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD2;
input.ki.wScan = 0;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Release ALT
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_LMENU;
input.ki.wScan = 0;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
SendInput(keystroke.size(), &keystroke[0], sizeof(keystroke[0]));
push_back
是在 for
循环中完成的,这就是为什么我每次都完全重新定义 input
变量。
这种方法似乎适用于除 Alt 代码之外的所有组合。我怎样才能让他们也工作?谢谢。
PS:如您所见,dwFlags
从未将 ALT (VK_LMENU)
声明为 ExtendedKey,因为根据我的理解,只有 VK_RMENU
(而不是 VK_LMENU
)是如此。 This MSDN page 似乎证实了这一点。
使用扫描码代替虚拟键。这将键注入系统的级别要低得多,并且比虚拟键更可靠地模拟真实用户键入。
我花了一段时间才找到最终的扫描码列表,因为其中存在一些差异。但是从 this page 中间的大 table 引用 "set 1" 列似乎可行。
INPUT createScanCodeEvent(WORD scancode, bool isDown)
{
INPUT input = {};
input.type = INPUT_KEYBOARD;
input.ki.wVk = 0;
input.ki.wScan = scancode;
input.ki.dwFlags = (isDown ? 0 : KEYEVENTF_KEYUP) | KEYEVENTF_SCANCODE;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
return input;
}
int inject()
{
std::vector<INPUT> keystroke;
const WORD SCANCODE_ALT = 0x38;
const WORD SCANCODE_NUMPAD_1 = 0x4f;
const WORD SCANCODE_NUMPAD_2 = 0x50;
keystroke.push_back(createScanCodeEvent(SCANCODE_ALT, true) );
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_2, true));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_2, false));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_1, true));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_1, false));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_2, true));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_2, false));
keystroke.push_back(createScanCodeEvent(SCANCODE_ALT, false));
SendInput(keystroke.size(), keystroke.data(), sizeof(keystroke[0]));
return 0;
}
在我正在开发的程序中,我必须模拟击键,为此我使用 SendInput()
方法,将包含作为击键一部分的输入的向量作为参数传递。我当前的代码似乎适用于我正在测试的所有组合,但 Alt 代码除外。
这是我目前所做的:
// Press ALT
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_LMENU;
input.ki.wScan = 0;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Press NumPad2
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD2;
input.ki.wScan = 0;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Release NumPad2
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD2;
input.ki.wScan = 0;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Press NumPad1
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD1;
input.ki.wScan = 0;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Release NumPad1
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD1;
input.ki.wScan = 0;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Press NumPad2
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD2;
input.ki.wScan = 0;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Release NumPad2
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_NUMPAD2;
input.ki.wScan = 0;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
// Release ALT
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_LMENU;
input.ki.wScan = 0;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
keystroke.push_back(input);
SendInput(keystroke.size(), &keystroke[0], sizeof(keystroke[0]));
push_back
是在 for
循环中完成的,这就是为什么我每次都完全重新定义 input
变量。
这种方法似乎适用于除 Alt 代码之外的所有组合。我怎样才能让他们也工作?谢谢。
PS:如您所见,dwFlags
从未将 ALT (VK_LMENU)
声明为 ExtendedKey,因为根据我的理解,只有 VK_RMENU
(而不是 VK_LMENU
)是如此。 This MSDN page 似乎证实了这一点。
使用扫描码代替虚拟键。这将键注入系统的级别要低得多,并且比虚拟键更可靠地模拟真实用户键入。
我花了一段时间才找到最终的扫描码列表,因为其中存在一些差异。但是从 this page 中间的大 table 引用 "set 1" 列似乎可行。
INPUT createScanCodeEvent(WORD scancode, bool isDown)
{
INPUT input = {};
input.type = INPUT_KEYBOARD;
input.ki.wVk = 0;
input.ki.wScan = scancode;
input.ki.dwFlags = (isDown ? 0 : KEYEVENTF_KEYUP) | KEYEVENTF_SCANCODE;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
return input;
}
int inject()
{
std::vector<INPUT> keystroke;
const WORD SCANCODE_ALT = 0x38;
const WORD SCANCODE_NUMPAD_1 = 0x4f;
const WORD SCANCODE_NUMPAD_2 = 0x50;
keystroke.push_back(createScanCodeEvent(SCANCODE_ALT, true) );
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_2, true));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_2, false));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_1, true));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_1, false));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_2, true));
keystroke.push_back(createScanCodeEvent(SCANCODE_NUMPAD_2, false));
keystroke.push_back(createScanCodeEvent(SCANCODE_ALT, false));
SendInput(keystroke.size(), keystroke.data(), sizeof(keystroke[0]));
return 0;
}