如何使用SendInput()指定kbd修饰符?

时间:2009-03-19 11:13:34

标签: c winapi keyboard-events

我正在使用Windows API SendInput()调用来模拟键盘事件。以下代码段(省略了相关的详细信息)非常适合发送一系列字符:

wchar_t txt = ...;
INPUT *input = ...;
size_t nInput = 0;

for (unsigned int j = 0; j < length; j++) {
    input[nInput].ki.wVk = 0;
    input[nInput].ki.wScan = txt[j];
    input[nInput].ki.dwFlags = KEYEVENTF_UNICODE;
    nInput++;
    input[nInput].ki.wVk = 0;
    input[nInput].ki.wScan = txt[j];
    input[nInput].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
    nInput++;
}
SendInput(nInput, input, sizeoF(INPUT));

现在我正在尝试使用修饰符发送单个按键。我尝试了以下代码:

bool control, alt shift;
wchar_t chr;

if (control) {
    input[nInput].ki.wVk = VK_CONTROL;
    input[nInput].ki.dwFlags = 0;
    nInput++;
}
if (alt) {
    input[nInput].ki.wVk = VK_MENU;
    input[nInput].ki.dwFlags = 0;
    nInput++;
}
if (shift) {
    input[nInput].ki.wVk = VK_SHIFT;
    input[nInput].ki.dwFlags = 0;
    nInput++;
}

input[nInput].ki.wVk = 0;
input[nInput].ki.wScan = chr;
input[nInput].ki.dwFlags = KEYEVENTF_UNICODE;
nInput++;
input[nInput].ki.wVk = 0;
input[nInput].ki.wScan = chr;
input[nInput].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
nInput++;

if (shift) {
    input[nInput].ki.wVk = VK_SHIFT;
    input[nInput].ki.dwFlags = KEYEVENTF_KEYUP;
    nInput++;
}
if (alt) {
    input[nInput].ki.wVk = VK_MENU;
    input[nInput].ki.dwFlags = KEYEVENTF_KEYUP;
    nInput++;
}
if (control) {
    input[nInput].ki.wVk = VK_CONTROL;
    input[nInput].ki.dwFlags = KEYEVENTF_KEYUP;
    nInput++;
}
SendInput(nInput, input, sizeof(INPUT));

但是,修饰符似乎没有通过,即,即使将control设置为true,事件序列也会作为普通按键接收。

2 个答案:

答案 0 :(得分:3)

Pax's answer没有成功,但它引导我找到正确的解决方案。简而言之:不要将KEYEVENTF_UNICODE用于单个按键,而是将字符转换为虚拟键代码,并以此方式发送。这是相关的代码:

SHORT virtKey = VkKeyScan((TCHAR) chr);
input[nInput].ki.wVk = LOBYTE(virtKey);
input[nInput].ki.dwFlags = 0;
nInput++;
input[nInput].ki.wVk = LOBYTE(virtKey);
input[nInput].ki.dwFlags = KEYEVENTF_KEYUP;
nInput++;

我还没有测试过如何处理映射到非英语键盘布局的非ASCII unicode字符,以及当我的应用程序的布局设置与前面应用程序的布局设置不同时会发生什么。

答案 1 :(得分:2)

我发现的唯一可能表明您的问题的代码也会在ki结构中设置扫描代码。

尝试将修改器部分更改为:

if (control) {
    input[nInput].ki.wVk = VK_CONTROL;
    input[nInput].ki.dwFlags = 0;
    input[nInput].ki.wScan = MapVirtualKey(VK_CONTROL, 0); 
    nInput++;
}
if (alt) {
    input[nInput].ki.wVk = VK_MENU;
    input[nInput].ki.dwFlags = 0;
    input[nInput].ki.wScan = MapVirtualKey(VK_MENU, 0); 
    nInput++;
}
if (shift) {
    input[nInput].ki.wVk = VK_SHIFT;
    input[nInput].ki.dwFlags = 0;
    input[nInput].ki.wScan = MapVirtualKey(VK_SHIFT, 0); 
    nInput++;
}

看看是否有帮助。

如果仍然无效,请尝试将dwFlags设置为KEYEVENTF_SCANCODE而不是0(仅适用于修改键)。

同样也为关键活动做这件事,我假设您将input[nInput].type设为INPUT_KEYBOARD,是吗?您的代码没有表明这一点。

作为参考,它在this page上找到。