pouët.net

Keyboard simulation, SendInput and Press events

category: code [glöplog]
 
Hey, guys!
I believe that some of you have coded a keyboard simulator before using WinAPI's SendInput or something similar and could help me.

I have read that the SendInput function realizes a low-level simulation of a keyboard and with that in mind I've created this class http://ideone.com/HqaBz and tested with the following codes:

Code:#include "Input.h" int main() { Input::Simulator::Keyboard kbd; Sleep(2000); /* Giving me some time to switch the focus */ kbd.press(kbd.SHIFT); kbd.hit('A'); kbd.hit('B'); kbd.release(kbd.SHIFT); return 0; }


This one above works just fine. The shift key is kept pressed and the characters are printed in uppercase. The problem is with the next one:

Code:#include "Input.h" int main() { Input::Simulator::Keyboard kbd; Sleep(2000); /* Giving me some time to switch the focus */ kbd.press('A'); for(;;); return 0; }


The key is pressed, but the press event isn't triggered. I couldn't find any solution online to solve it. Does anyone have any idea of how to make it work?
added on the 2012-07-14 07:44:04 by Danguafer Danguafer
And no, I'm not into mmo's.
added on the 2012-07-14 07:45:14 by Danguafer Danguafer
Do you have to add:
kbd.release(kbd.A);

to complete the cycle?

Sounds logical to me. Not that I've done any coding like that.
added on the 2012-07-14 09:19:25 by Gmitts Gmitts
Just use the native API...
added on the 2012-07-14 14:37:11 by TLM TLM
kbd.hit('A');
added on the 2012-07-14 15:21:10 by Fell Fell
i made own static keyboard class not long ago for my own projects. might just paste the code here:

header file
Code: // //Keyboard Class // #ifndef __KEYBOARD_H__ #define __KEYBOARD_H__ #include <windows.h> #include <io.h> #include <fcntl.h> #include "../../Common.h" class Keyboard { public: Keyboard(); static uchar KeyPressed(int vKey); static void AutoKeyDown(UINT key); static void AutoKeyUp(UINT key); private: static uchar flag[256]; //key states }; #endif


cpp file
Code: #include "Keyboard.h" uchar Keyboard::flag[256]; Keyboard::Keyboard() { for (ushort i=0; i<256; i++) flag[i] = 1; } // //Determine whether a key is up or down at the time the GetAsyncKeyState function is called, //and whether the key was pressed after a previous call to GetAsyncKeyState. // uchar Keyboard::KeyPressed(int vKey) { //the return value specifies whether the key was pressed since the last call and whether the key is currently up or down. //if the most significant bit is set, the key is down, and if the least significant bit is set, //the key was pressed after the previous call to GetAsyncKeyState. short retval = GetAsyncKeyState(vKey); //key pressed? (up or down?) uchar keyDown = ((retval & 0x8000) >> 15); char ret = flag[vKey]?keyDown:0; flag[vKey] = !keyDown; //motsatte av keyup (altsaa om tasten er releasa) return ret; } void Keyboard::AutoKeyDown(UINT key) { UINT vkCode = LOBYTE(VkKeyScan(key)); keybd_event(key, MapVirtualKey(vkCode, 0), 0, 0); } void Keyboard::AutoKeyUp(UINT key) { UINT vkCode = LOBYTE(VkKeyScan(key)); keybd_event(key, MapVirtualKey(vkCode, 0), KEYEVENTF_KEYUP, 0); }


So doing something like Keyboard::AutoKeyDown(VK_A or 'A'); or something like that should do it iirc. or you might just do something like this (if you want to read keypresses in your demoloop or whatever:

Code: if (Keyboard::KeyPressed(VK_UP)) doSomething();
added on the 2012-07-14 15:24:14 by rudi rudi
ah, i found some code for it.
this is what i did when i attached an console window using those autofunctions:

example:
Code: void Console::DockLeft() { SetForegroundWindow(consoleWnd); Keyboard::AutoKeyDown(VK_LWIN); Keyboard::AutoKeyDown(VK_LEFT); Keyboard::AutoKeyUp(VK_LEFT); Keyboard::AutoKeyUp(VK_LWIN); }
added on the 2012-07-14 15:27:08 by rudi rudi
It keeps don't working. I've tested it with mIRC and Max Payne 3 (:3). Holding 'W' (kbd.press('W')) for an undefined amount of time (without kbd.release('W')'ing) on mIRC only prints one 'W' (it doesn't repeat) while holding 'W' on Max Payne 3 makes the character walk.

I don't know much about Windows programming, but I believe that this key repeat bullshit is implemented using a keypress event as a default behavior by the own OS, or something like that, which isn't being executed. Max Payne 3 probably uses DirectInput and it's working OK. Do I really need to write a driver for simulating a keyboard properly? :(
added on the 2012-07-14 18:53:28 by Danguafer Danguafer
being negative doesnt help. really.
added on the 2012-07-14 19:16:59 by rudi rudi
"Repeating keystrokes is a feature of the keyboard controller, not of Windows or SendInput. You can certainly emulate it with a timer, repeatedly calling SendInput()."

OOOOOOOOOOOOK!!! Problem solved. Someone gave me the wrong information.
added on the 2012-07-14 19:47:22 by Danguafer Danguafer
I like AutoHotkey You can script mouse events in addition to keyboard. The scripts are plain text files and comes with many examples to hack around. works great to macro ssf4t moves or do something weird like focus on a window. docs are extensive.

Code:Send ^c!{tab}pasted:^v Send Sincerely,{Enter}John Smith

login