2016-12-13 1 views
-1

Я работаю над проектом, где я взял контроллер Super Nintendo, управляя его с помощью Arduino. Arduino считывает нажатие кнопки на контроллере и отправляет его по последовательному соединению.Имитация ключа удерживается в C и WINAPI

Я работаю над программой-получателем, которая будет считываться из последовательного порта, а затем имитирует нажатия клавиш в Windows, поэтому я могу использовать контроллер в других программах.

Дело в том, что я получил почти все. За исключением одной проблемы. Мои симулированные нажатия клавиш фактически не удерживаются.

Вот код для кнопки A (кнопки активны с низким, так что они являются «ложными», когда нажата)

if(!(buttonState.state_word & B_A)) 
{ 
    /* If previous state is not pressed, and current is pressed, simulate a keypress */ 
    if(prevState.state_word & B_A) 
     keybd_event(0x41, 0x41,KEYEVENTF_EXTENDEDKEY | 0,0); 
} 
else if(buttonState.state_word & B_A) 
{ 
    /* If previous state is pressed, and current is not pressed, simulate a key release */ 
    if(!(prevState.state_word & B_A)) 
     keybd_event(0x41, 0x41,KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,0); 
} 

Когда я нажимаю на контроллере SNES, Л появится в блокноте , например. И когда я удерживаю кнопку A на контроллере SNES, в блокноте появляется один A, но терминал будет печатать, что ключ удерживается, как я его запрограммировал.

Когда кнопка сначала нажата, а не нажата, она имитирует нажатие клавиши. Когда он удерживается, больше вызовов для имитации нажатия клавиши не производится. И затем, когда кнопка SNES отпущена, клавиша также отпущена.

Поскольку есть время между нажатием клавиши и клавиатурой, почему печатается только одна буква, а не как если бы клавиатура удерживалась и печаталась многократно?

+0

Когда обновляется? PrevState? –

+0

Похоже, вы хотите, чтобы клавиши были «типичными». Я не знаю, работает ли это с имитируемыми событиями клавиатуры в Windows. –

+0

вам вообще не нужно поддерживать кнопки кнопок. когда вы получили удаленное событие (keydown или keyup), вам нужен прямой вызов 'keybd_event' без каких-либо проверок и условий. – RbMm

ответ

0

Спасибо всем, кто ответил.

В итоге я решил использовать другой подход, используя SendInput вместо этого на этот раз, и теперь он работает как шарм.

Что касается причины, в то время как я сохраняю состояние, то, как я это видел, было, если кнопка удерживается, я не хочу имитировать другое нажатие при каждом опросе контроллера. Поэтому я сохраняю состояние, так что, если кнопка нажата, и в следующий раз, когда он будет опрошен, он все еще нажат, я не буду генерировать другое нажатие. Он будет генерироваться только тогда, когда последнее состояние контроллера показало, что оно не было нажато.

while(1) 
{ 
    prevState = buttonState; 
    ReadFile( hCOM, 
       &buttonState.state_word, 
       2, 
       &bytesRead, 
       NULL); 

    for(i = 0; i < 12; i++) 
    { 
     if(!(buttonState.state_word & (1 << i))) 
     { 
      /* If previous state is not pressed, and current is pressed, simulate a keypress */ 
      if(prevState.state_word & (1 << i)) 
      { 
       in[i].ki.dwFlags = KEYEVENTF_SCANCODE; 
       SendInput(1,&in[i],sizeof(INPUT)); 
      } 
     } 
     else if(buttonState.state_word & (1 << i)) 
     { 
      /* If previous state is pressed, and current is not pressed, simulate a key release */ 
      if(!(prevState.state_word & (1 << i))) 
      { 
       in[i].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; 
       SendInput(1,&in[i],sizeof(INPUT)); 
      } 
     } 
    } 

} 
+0

Это звучит как проект хобби, но если вы хотите превратить его профессионалом, вы должны поменять его на ReadFile() для ReadFileEx() и использовать асинхронный ввод-вывод Windows. Это, в свою очередь, означает, что нить не будет потреблять 100% -ный процессор, как ваша текущая программа. – Lundin

+0

@ Lundin: Синхронный ввод-вывод не решает проблему, которую вы создали, перейдя асинхронно? – IInspectable

+0

@Инспективный Что вы имеете в виду? – Lundin

Смежные вопросы