2

我正在使用 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,事件序列也会作为普通按键接收。

4

2 回答 2

3

Pax 的回答没有奏效,但它引导我找到了正确的解决方案。简而言之:不要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 字符是如何工作的,以及当我的应用程序的布局集与前面的应用程序的布局集不同时会发生什么。

于 2009-03-19T12:28:59.383 回答
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++;
}

看看是否有帮助。

如果这仍然不起作用,请尝试设置dwFlagstoKEYEVENTF_SCANCODE而不是0(仅适用于修饰键)。

也为按键事件执行此操作,我假设您设置input[nInput].typeINPUT_KEYBOARD,是吗?您的代码没有表明这一点。

作为参考,它是在这个页面上找到的。

于 2009-03-19T11:50:40.287 回答