Jump to content
  • Advertisement
Sign in to follow this  
Mybowlcut

[C++] PeekConsoleInput

This topic is 3839 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?



Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!