Как указать модификаторы kbd с помощью SendInput ()? - PullRequest
2 голосов
/ 19 марта 2009

Я использую вызов 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 ]

3 голосов
/ 19 марта 2009

ответ Пакс не сработал, но он привел меня к правильному решению. Вкратце: не используйте 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 символов Юникода, которые сопоставлены с неанглоязычными раскладками клавиатуры, и что происходит, когда макет, установленный для моего приложения, отличается от макета, установленного для приложения на передней панели.

2 голосов
/ 19 марта 2009

Единственный найденный фрагмент кода, который может указывать на вашу проблему, также устанавливает код сканирования в структуру 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, да? Ваш код не указывает на это.

Для справки, он был найден на этой странице .

...