Ignore held down key press with pdcurses - c++

#include <curses.h>
#include "SourceFiles/generalFunc.h"
int main(){
initscr();
cbreak();
noecho();
wtimeout(stdscr,0); //NON-BLOCKING IO. getch returns ERR if no input is read.
int x = 0;
sleepMilli(3000); //three seconds
while((x = wgetch(stdscr)) != ERR){
x = wgetch(stdscr);
//flushinp();
waddch(stdscr,x);
wrefresh(stdscr);
}
waddstr(stdscr, " THAT'S ALL FOLKS!");
wrefresh(stdscr);
sleepMilli(2000);
endwin();
}
sleepMilli is a function that waits for however many milliseconds.
I am writing a program that detects a key press, does some work, waits a certain amount of time t, and then detects another key press and does some work, and so on. Of course if t is large and the user has held down a key, that key repeats itself in the input buffer, so when the user lets go of the key the program will carry on processing that input buffer until it is done with the repeated key input. That's going to look weird, especially if that repeated key moves the terminal cursor (it will carry on moving long after the user lets go).
I need a way to read ONE input from the held down key, and then discard the rest. I thought that was what flushinp() did, but I realised I was wrong. In the above program, if flushinp() is commented out, then with input such as:
cvcvcvcvcvcvcv
(so I am not holding down a key) The output is:
cvcvcvcvcvcvcv
If I hold down the key c then the output is:
cccccccccccccc
If I uncomment flushinp() and do the same two inputs, the outputs are:
c
and
cccccccccccccc
So flushinp() only works for singular key presses, but not repeated key events. Is it possible (on 64-bit Windows) to just read one input from a held down key and discard the rest? I don't want to turn off repeat keys completely, because obviously I want the user to be able to move the cursor continuously by holding down a key.

Related

How to use DeviceIOControl to send keyboard press to a video game?

I am trying to make a way of passing keyboard and mouse inputs over a LAN connection. While I have been successful at doing this using the SendInput() function for things like Notepad and Visual Studio, the inputs are not registered in many video games. After doing some research, it appears that I'll need to use DeviceIOControl to accomplish the task, however I have no idea how I am supposed to do this when the keycodes have to be determined at runtime.
I'm not sure if I can just arbitrarily set the hDevice parameter to the incoming keycode or not, or what the code would look like in the end.
If it helps, the below code is what is currently being used to input key presses. The server receives a string which is parsed out to determine the key press and the state of the key (whether it's a key up or key down event). This information is passed as the parameters to this function:
void keyPress(WORD k, int state)
{
INPUT Inputs;
std::cout<<"Key="<<k<<", state="<<state<<std::endl;
Inputs.type=INPUT_KEYBOARD;
Inputs.ki.wVk=k;
if(state==1)
{
Inputs.ki.dwFlags=0;
SendInput(1, &Inputs, sizeof(INPUT));
}
else
{
Inputs.ki.dwFlags=KEYEVENTF_KEYUP;
SendInput(1, &Inputs, sizeof(INPUT));
}
if((int)k!=0) //Keycode of 0 means that the last key pressed is being held down.
{
LastKey=k;
key[ 0]=LastKey;
}
}
Also, if I am going down the wrong rabbit hole and there is a better solution, please let me know!
Thank you,

using c++ input stream cin without blocking

I am trying to use the c++ standard input stream cin to get a user input without blocking the execution of the program. I have this code:
char ch;
int flag=1;
do
{
if(cin.rdbuf()->in_avail())
{
cin.get(ch);
flag=0;
}
else
//do something else
}while(flag);
//do something with the input
The idea here is to wait for user input without blocking while doing something else and as soon as the user provides an input we process the input( all in one thread). I know from the documentation the streambuf class used by the input stream provides the in_avail() function which will return a non-zero values when ever there is input ready in the buffer. The code above is not working as i expected it and is looping forever even if i provide a keyboard input at some point. i am using MS visual studio 2005 in windows 7. what am i missing here?
The function in_avail does:
Returns the number of characters available in the get area.
The get area may be empty even if some characters are readable from the underlying operating system buffer.
You will trigger a refill of the get area when you effectively call a read operation on the streambuf. And that operation will block. The reason is that the method underflow which is responsible for filling the get area:
Ensures that at least one character is available in the input area
And to ensure this, it must block until some character is read.

Creating Alt Codes on a Laptop Without Them

My laptop has a number pad, but it does not have a NumLock key, and the numpad is actually just a copy of the row of numbers above the letters. This is confirmed by the virtual key codes sent when I press these keys.
I'm trying to develop a small program to mimic alt codes when the alt key and regular numbers are pressed. I use a low-level keyboard hook (I have a similar format working in another program), and first check to see if either alt key is down. If either is, I loop through the VK codes 0x30-0x39 (0-9 keys). If one of those is pressed down at that moment, I discard the actual keystroke by returning a value of 1, and instead send a numpad version of that key instead (alt is still pressed down at this time).
I can confirm that the hook is being reached, and that the alt key being down is being recognized successfully. However, when I check for matches on 0-9, either only a couple are printed before nothing matches after that, or I have to lift up and press down the alt key every time I press a number. Additionally, one number may be printed 16 times after releasing alt having pressed a number, and then holding down alt and pressing another (this one is 16x).
Also, I can confirm the SendInput sequence works via copying the part from the hook, putting it into the main function and replacing i with 0x30. Upon running, a 0 will be typed onto the text document.
When holding down ALT(down)+6+5+ALT(up) in a text document, "65" is what shows. If I add another ALT(down)+6, 16 sixes appear.
Hook Procedure:
LRESULT CALLBACK proc (int code, WPARAM wParam, LPARAM event) //hook proc
{
if (code < HC_ACTION) //don't process if not meant to
return CallNextHookEx (0, code, wParam, event);
if (GetAsyncKeyState (VK_MENU) & 0x8000) //if either alt is down
{
for (int i = 0x30; i <= 0x39; ++i) //loop 0-9
{
if (GetAsyncKeyState (i) & 0x8000) //if index is down
{
cout << "MATCH\n"; //debug
input.ki.wVk = i + 0x30; //set VK code to numpad version of index
input.ki.dwFlags = 0; //key is being pressed
SendInput (1, &input, sizeof (INPUT)); //send keystroke down
input.ki.dwFlags = KEYEVENTF_KEYUP; //key is being released
SendInput (1, &input, sizeof (INPUT)); //send keystroke up
while (GetAsyncKeyState (i) & 0x8000) //wait for normal key to be released
Sleep (10); //don't hog CPU
return 1; //discard normal key
} //end if match
} //end for
} //end if alt
return CallNextHookEx (0, code, wParam, event); //if any key not handled, pass on
} //end function
Well, I finally came back to this and after some more testing I discovered that programmatically sending [ALT ] [num6] [num5] [ALT ] does nothing whatsoever. I find this odd because I am able to simulate the volume control keys on the Mac keyboards despite not having those keys.
Since the computer simply can't send alt codes, I declare this helpful tool royally screwed unless I map thousands of characters.
EDIT:
Here's what you need to do to get the number pad working on the G74SX-XA1:
Download the BIOS 203 (I don't know if 202 works or not, I went from 201 to 203).
Put the file on a FAT32-formatted flash drive.
Restart the computer and either press F4 to go right into EasyFlash, or navigate to it through the BIOS. The Winflash program that comes with it doesn't work.
Select the updated BIOS file on the flash drive.
Now the numlock light will always be on and the number pad will have the virtual key codes of a number pad, not the numbers above the letters. This naturally includes ALT codes working.

Getting input without a linebreak

I'm writing a program which will be doing manipulation of matrices. I want the user to be able to enter data into a matrix by typing it in one row at a time. So it will first ask for the value in row: 1, column: 1. The user will type in the appropriate value, and then press enter, after which he will type in the value for row: 1, column: 2.
This is the trick: I want the console to not enter a new line when the user presses enter. Instead, I want it to simply insert a tab character. Is this possible?
Thanks so much.
Yes, it's possible. You'll need to use a console/terminal library, though. Ncurses for *nix, wincon (part of the Windows API; you can just #include windows.h to use it)... There are a lot of choices out there.
The actual algorithm will simply be checking the characters that are sent as key events/using the getkey() equivalents of the various libraries, outputting the inputted characters to the console if the key pressed is not ENTER but would still cause a character to be echoed to the screen (i.e. function keys, caps lock, shift, etc. wouldn't cause any echoing to the console or terminal window) and then outputting \t if the key pressed is indeed ENTER.
Set the cursor position back up to the previous line. In Windows, you can use SetConsoleCursorPosition().
It's not exactly what you wanted, but you could get the same effect by using getline to obtain the row input all on one line, and then use std::stringstream to parse out the values.
std::string row;
getline(cin,row);
std::stringstream ss(row);
int j=0,i=currentrow; //put this in a loop over your rows
int input; //or float, double, whatever
while(ss >> input)
{
mat[i][j] = input;
j++;
}

How to repeat key strokes with SendInput?

I'm writing a little tool in VC++ to record key strokes to replay them later, a macro recorder. It works quite nice already, using a keyboard hook function that reads each and every key press and release event. The playback works with the SendInput() function and generally also works fine - except for repeating key strokes. Pressing a key several times after releasing it every time is no problem. But pressing it and holding it down, for the input character to be repeated, can be recorded but can only be replayed in some applications. Some accept and enter the character multiple times, some do it only once. (It is reproducible which does which.) The macro recorder itself also sees the held down key pressed just a single time during playback, through its monitoring hook.
So, how can I make SendInput send multiple subsequent key strokes of a single key without adding key release events on my own in between? Sending a sequence of [press] [press] [press] ... [release] doesn't always work.
You could send Multiple keys in one SendInput calls, but you will still need to set keyup flags on every char to get same results on every type of keystrokes.
if you need to send "aa", you can do like this.
INPUT input[4];
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = 0;
input[0].ki.wScan = 'a';
input[0].ki.dwFlags = 0;
input[1].type = INPUT_KEYBOARD;
input[1].ki.wVk = 0;
input[1].ki.wScan = 'a';
input[1].ki.dwFlags = KEYEVENTF_KEYUP;
input[2].type = INPUT_KEYBOARD;
input[2].ki.wVk = 0;
input[2].ki.wScan = 'a';
input[2].ki.dwFlags = 0;
input[3].type = INPUT_KEYBOARD;
input[3].ki.wVk = 0;
input[3].ki.wScan = 'a';
input[3].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(4, input, sizeof(INPUT));
I'm not sure about your exact sequence of keystrokes, but I had a similar issue recently. I wrote a tiny Win32 tool [1] to send keys when a global shortcut key is pressed. When characters were repeated, e.g., "aaabc", the repeated characters were lost. I tried many combinations of KeyDown and KeyUp, but repeated characters were always lost.
Then I found this blog post: https://batchloaf.wordpress.com/2014/10/02/using-sendinput-to-type-unicode-characters/
While the author does not specifically discuss repeating characters, it inspired me to try SendInput() with only a single INPUT structure. This technique works very well for me.
In short:
Call SendInput() with only a single INPUT structure.
To simulate a single typed (regular) key, e.g., z, try this:
Send single KeyDown event: ki.dwFlags = KEYEVENTF_UNICODE
Send single KeyUp event: ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP
[1] https://github.com/kevinarpe/win32/tree/master/send_input
Many people experience issues with the keyup and keydown calls being "dismissed" or "dropped", and alot of people have resolved their problems by placing a small buffer amount of time between the two, to assure that all commands are transfered:
sendinput alt keydown
sendinput 3 keydown
sleep 50
sendinput 3 keyup
sendinput alt keyup
There's also a SendInput.SendWait command....
Cheers
As far as I know, the way it works is if a key down event is received with no key up event for a certain period of time (the repeat delay), the key is considered "repeating" until a key up occurs.
Since sending press, press, press, release doesn't work always, have you tried recording the time between the key down and key up, then repeating the commands in that same time? It becomes real time, but it should trigger the same repeat actions that way.
I can't think of any other way to end up with the same amount of "key repeats" as the original since those aren't recorded as individual key presses.