SendInput() 无法正确管理 Alt 代码



在我正在开发的程序中,我必须模拟击键,为此,我使用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 s是在for周期中完成的,这就是为什么我每次都完全重新定义input变量的原因。

这种方法似乎适用于除 Alt 代码以外的所有组合。我怎样才能让它们也工作?谢谢。

PS:正如您所注意到的,dwFlags从不将ALT (VK_LMENU)声明为扩展密钥,因为据我了解,只有VK_RMENU(而不是VK_LMENU(是这样的。此 MSDN 页面似乎证实了这一点。

使用扫描码而不是虚拟键。这会将按键注入到系统中的级别要低得多,并且比虚拟键更可靠地模拟真实用户键入。

我花了一段时间才找到扫描代码的最终列表,因为那里有一些差异。 但是引用本页中间大表中的"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;
}

最新更新