[C++] PeekConsoleInput

Started by
10 comments, last by Purple-Haze 16 years, 2 months ago
Hey. I've got two functions: one which gets a keypress (removes it from buffer) and returns it and one which returns the (last I hope?) keypress (without removing it from buffer). The only problem is, the second cout statement always prints out: 0 0
#include <windows.h>
#include <iostream>

class Keypress
{
public:
	Keypress() : virtual_key(0), control_key(0) {}
	Keypress(WORD virtual_key, DWORD control_key)
		: virtual_key(virtual_key),	control_key(control_key) {}
	WORD virtual_key;
	DWORD control_key;
};

Keypress get_keypress()
{
	HANDLE input_handle = GetStdHandle(STD_INPUT_HANDLE);
	DWORD events = 0;			// how many events took place
	INPUT_RECORD input_record;	// a record of input events
	DWORD input_size = 1;		// how many characters to read
	bool not_a_keypress = true;
	Keypress keypress;

	do
	{
		// Stop from echoing.
		FlushConsoleInputBuffer(input_handle);
		ReadConsoleInput(input_handle, &input_record, input_size, &events);
		
		if(input_record.EventType == KEY_EVENT && input_record.Event.KeyEvent.bKeyDown)
		{ // A key was pressed, so return it.
			keypress.virtual_key = input_record.Event.KeyEvent.wVirtualKeyCode;
			keypress.control_key = input_record.Event.KeyEvent.dwControlKeyState;
			not_a_keypress = false;
		}
	} while(not_a_keypress);
	// Should not be reached.
	return keypress;
}

Keypress peek_keypress()
{
	HANDLE input_handle = GetStdHandle(STD_INPUT_HANDLE);
	DWORD events = 0;			// how many events took place
	INPUT_RECORD input_record;	// a record of input events
	DWORD input_size = 1;		// how many characters to read

	BOOL peeked = PeekConsoleInput(input_handle, &input_record, input_size, &events);

	Keypress keypress;
	if(peeked && input_record.EventType == KEY_EVENT)
	{ // PeekConsoleInput succeeded and a key was pressed, so set and return keypress.
		keypress.virtual_key = input_record.Event.KeyEvent.wVirtualKeyCode;
		keypress.control_key = input_record.Event.KeyEvent.dwControlKeyState;
	}
	return keypress;
}

int main()
{
	Keypress k;
	Keypress k2;

	while(k.virtual_key != VK_ESCAPE)
	{
		// Get a keypress.
		k = get_keypress();
		// Peek at the last keypress.
		k2 = peek_keypress();

		std::cout << k.virtual_key << " " << k.control_key << std::endl;
		std::cout << k2.virtual_key << " " << k2.control_key << std::endl;
	}
	return 0;
}

When I debug it, this line in peek_keypress has input_record.EventType equaling some junk value like 54248:
if(peeked && input_record.EventType == KEY_EVENT)

Anyone know why this code isn't working? Cheers.

Advertisement
Try defining input_record as
INPUT_RECORD input_record[1]


Also, call should be
BOOL peeked = PeekConsoleInput(input_handle, input_record, input_size, &events);


Oh, and use
input_record[0]

when you access members
--------------------------------------"Those alien bastards are gonna pay for ruining my ride !"
I did what you suggested but nothing changes. I don't think it would matter anyway, since the function still works using just the struct as evidenced by the return value which is 1 for both ReadConsoleInput and PeekConsoleInput when I tested it. Can you think of any other reasons why this might be happening?

Quote:Original post by Mybowlcut
I did what you suggested but nothing changes. I don't think it would matter anyway, since the function still works using just the struct as evidenced by the return value which is 1 for both ReadConsoleInput and PeekConsoleInput when I tested it. Can you think of any other reasons why this might be happening?

Hmm, It could be a timing issue. input_handle may not be ready for you app to process.
Try
  DWORD wait = 200;  WaitForSingleObject(input_handle,wait);  BOOL peeked = PeekConsoleInput(input_handle, &input_record, input_size, &events);

You might have to try a different wait too. I'm just going off of MSDN. I don't have a compiler with me now.

--------------------------------------"Those alien bastards are gonna pay for ruining my ride !"
Hey. I tried that and still no luck. I appreciate your help so far. :) Do you reckon that when you get to a compiler you could try the code sample I posted? That'd be awesome if you could.

Quote:Original post by Mybowlcut
Hey. I tried that and still no luck. I appreciate your help so far. :) Do you reckon that when you get to a compiler you could try the code sample I posted? That'd be awesome if you could.


I think I misunderstood what you're trying to do. What data do you expect the console input buffer to contain for peeking after you've "read" it? Or are you expecting to peek into the buffer before read processes it?



--------------------------------------"Those alien bastards are gonna pay for ruining my ride !"
I made an interface class called Updateable that returns void and takes no parameters. This means that each class that derives from Updateable needs to be able to get the lass keypress through peek_keypress (because it doesn't have any parameters to use - which is what I prefer). So:

GAME LOOP
GET_KEYPRESS() (USER PRESSES A KEY)
OBJECT.UPDATE() (CALLS PEEK_KEYPRESS)
OBJECT.DRAW()
GAME LOOP

Hope that clears things up.

Quote:Original post by Mybowlcut
I made an interface class called Updateable that returns void and takes no parameters. This means that each class that derives from Updateable needs to be able to get the lass keypress through peek_keypress (because it doesn't have any parameters to use - which is what I prefer). So:

GAME LOOP
GET_KEYPRESS() (USER PRESSES A KEY)
OBJECT.UPDATE() (CALLS PEEK_KEYPRESS)
OBJECT.DRAW()
GAME LOOP

Hope that clears things up.


OK. But..
ReadConsoleInput will wait for an input, process it and remove it from the inputbuffer. What do you expect to be able to Peek in your update function?

If you're simply trying to poll and maintain an input state ( with a one keystroke history? ) you should look into a different scheme for doing so.

You can simply use #PeekConsoleInput to find out how many events are pending to be processed and then process each one of them and maintain an inputstate in your base class which derived classes can access. You can simply use boolean fields for all the keys and update them on key up/down events.

Another way is to use direct input and and use the direct input device state to create a snapshot of the input state each game-loop-frame.

If you're trying to serialize the input.. ignore the above, and just use a queue :D
---
Not sure if thats what you wanted..
- K
--------------------------------------"Those alien bastards are gonna pay for ruining my ride !"
Ah! Of course! The KeyEvent is removed from the queue so there's nothing to peek! Hmm... I guess that what I wanted to do is have all the objects that need access to input call PeekConsoleInput to get the latest event, and then at the end of the game loop remove the latest event from the queue (once all the objects have called Update()). Is that possible? Is there a function to remove the event from the queue? Should I use ReadConsoleInput for that?

Cheers.

Quote:Original post by Mybowlcut
Ah! Of course! The KeyEvent is removed from the queue so there's nothing to peek! Hmm... I guess that what I wanted to do is have all the objects that need access to input call PeekConsoleInput to get the latest event, and then at the end of the game loop remove the latest event from the queue (once all the objects have called Update()). Is that possible? Is there a function to remove the event from the queue? Should I use ReadConsoleInput for that?
Cheers.

I'm not sure if the console buffer is the right way to proceed. For e.g. if you have multiple key events in the buffer then each object has to know about it before hand and then process each one.

I would probably go with making an input state data structure of 32 or whatever keys and update it each frame. You can either use the app message loop directly if possible w/ your framework or use an external lib. That way each object is de-coupled from the keyboard input mechanism and its easier to make changes. Thats just my .02, Not in anyway the only soln.... ( or even a good one ! :D )

- K
--------------------------------------"Those alien bastards are gonna pay for ruining my ride !"

This topic is closed to new replies.

Advertisement