2015-02-10 1 views
3

У меня есть простой кодНевозможно Имитировать Alt-Tab Virtual Key Press, отлично работает с другими клавишами

KEYBDINPUT k1 = { VK_MENU, 0, 0, 0, 0 }; 
KEYBDINPUT k2 = { VK_TAB, 0, 0, 0, 0 }; 
KEYBDINPUT k3 = { VK_TAB, 0, KEYEVENTF_KEYUP, 0, 0 }; 
KEYBDINPUT k4 = { VK_MENU, 0, KEYEVENTF_KEYUP, 0, 0 }; 
int cnt = 0; 

while (cnt < 10) 
{ 
    Sleep(1000); 
    INPUT in1 = { INPUT_KEYBOARD }; 
    in1.ki = k1; 
    SendInput(1, &in1, sizeof(INPUT)); 

    INPUT in2 = { INPUT_KEYBOARD }; 
    in2.ki = k2; 
    INPUT in3 = { INPUT_KEYBOARD }; 
    in3.ki = k3; 
    SendInput(1, &in2, sizeof(INPUT)); 
    SendInput(1, &in3, sizeof(INPUT)); 

    cnt++; 
} 

INPUT in4 = { INPUT_KEYBOARD }; 
in4.ki = k4; 
SendInput(1, &in4, sizeof(INPUT)); 

return 0; 

Это не работает. Если я изменюсь с VK_TAB на VK_ESCAPE, это сработает.

Я хотел бы эмулировать Alt-Tab, поскольку Alt-Esc не имеет визуального представления. Есть ли что-то особенное в VK_TAB?

+0

Вы пробовали передать SendInput массив с обоими событиями, а также проверить возвращаемое значение, чтобы увидеть, удалось ли вызов? –

+0

@RetiredNinja yes, попробовали это. Возвращаемое значение равно 1 при отправке события независимо и равно 2 при отправке их в массив – Adorn

+0

Передача '1' в качестве параметра' nInputs' для [SendInput] (https://msdn.microsoft. com/en-us/library/windows/desktop/ms646310.aspx) является олицетворением невежества: * «Эти события не чередуются с другими событиями ввода клавиатуры или мыши [...]» * – IInspectable

ответ

0

Когда VKs терпят неудачу, вместо этого часто используется SendInput с кодами сканирования клавиатуры.

Приведенный ниже пример демонстрирует, как имитировать альт-вкладку с кодами SendInput и клавиатуры.

Функция alt_tab принимает счет. Он будет симулировать удерживание левой клавиши Alt, нажав клавишу «кол-во» клавиши вкладок, а затем отпустив левую клавишу Alt.

Задержка нажатия клавиши довольно большая, в основном, чтобы дать достаточно времени, чтобы визуально продемонстрировать эффект. Более короткие задержки будут более эффективными для автоматизации, но вы, вероятно, не сможете полностью удалить их.

Я передаю 1 в качестве входного счетчика в SendInput, потому что я только хочу отправить его за раз. Манипуляция временными метками KEYBDINPUT не работает так, как можно было бы ожидать.

Чтобы создать этот пример, начните с проекта консоли Win32.

#include <Windows.h> 

void sendkey(WORD scan_code, bool tf_down_up, bool extended=false) { 
    INPUT input = {0}; 
    input.type = INPUT_KEYBOARD; 
    input.ki.wScan = scan_code; 
    input.ki.dwFlags     = KEYEVENTF_SCANCODE; 
    if(!tf_down_up) input.ki.dwFlags |= KEYEVENTF_KEYUP; 
    if(extended) input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; 
    SendInput(1, &input, sizeof(input)); 
} 

void keydown(WORD scan_code, bool extended=false) { 
    sendkey(scan_code, true, extended); 
} 

void keyup(WORD scan_code, bool extended=false) { 
    sendkey(scan_code, false, extended); 
} 

static const WORD TAB_SCANCODE  = 0x0f; 
static const WORD LEFT_ALT_SCANCODE = 0x38; 

static const DWORD keypress_delay_ms = 500; 

void alt_tab(int tab_count=1) { 
    keydown(LEFT_ALT_SCANCODE); 
    Sleep(keypress_delay_ms); 
    for(int i=0; i<tab_count; ++i) { 
     keydown(TAB_SCANCODE); 
     Sleep(keypress_delay_ms); 
     keyup(TAB_SCANCODE); 
     Sleep(keypress_delay_ms); 
    } 
    keyup(LEFT_ALT_SCANCODE); 
} 

int main() { 
    Sleep(1000); 
    alt_tab(3); 
} 
+2

Нет, серьезно, вы делаете ** не ** когда-либо хотите отправить одно входное событие. Когда-либо. * Key down * и * key up * события абсолютно ** должны ** не вставляться с другим вводом. Неспособность генерировать их в одном вызове 'SendInput' не дает надежного решения. Изучите [документацию] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310.aspx) в глубину. – IInspectable

+0

Невозможно было бы контролировать время ввода событий, если оно было бы обременено требованием обработки каждого набора входов как своего рода атомной транзакции. Все события в списке произойдут сразу, поэтому не будет никакого способа имитировать удерживание клавиши вниз на любой промежуток времени, который будет напоминать человеческое нажатие клавиши. Такая автоматизация не ожидает борьбы с человеком с клавиатуры. –

+0

[SendInput] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310.aspx): * «Функция SendInput вставляет события в структурах INPUT ** последовательно * на клавиатуру или входной поток мыши. "* (выделение мое) – IInspectable