Keyboard input Windows

Started by
9 comments, last by Mumsfilibaba 8 years ago
Hi, quick question. How do I handle multiple keystrokes in Windows? At the moment I use the messageloop, and for every WM_KEYDOWN I check which key got pressed (translate it into an enum) and add it to a list with pressed keys. Then in my GetKeyDown method I loop through the list of pressed keys and return true if the key are in the list. But it seems like only one key gets registered every frame. If I hold down a key it gets registered, but if I hold down one other key at the same time, only the new one gets added. So is this a Windows thing? Should I do it in another way?
Advertisement
post the relevant code. (message loop and getkeydown method)
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

Probably irrelevant here, but `keyboard ghosting` is a thing.

How do I handle multiple keystrokes in Windows?

Usually keyboard events are buffered and then the keyboard state is updated using these. You buffer them the closest as possible to the frame rendering in an attempt to decrease input latency.

So is this a Windows thing? Should I do it in another way?

No. There is no Win32 documentation stating such thing. If you're holding a key you'll just receive multiple WM_KEYDOWN events.

I suspect you're processing only one window event per frame. Paste your event loop here please.

IIRC GLFW has a very readable handling of keyboard events. Maybe you check that out if you think that should help.


No. There is no Win32 documentation stating such thing. If you're holding a key you'll just receive multiple WM_KEYDOWN events.

No. When you press a key, a WM_KEYDOWN is sent, and when you release the key, a WM_KEYUP is sent. The WM_KEYPRESSED message repeats during the hold, but it is less useful for game input.

No. When you press a key, a WM_KEYDOWN is sent, and when you release the key, a WM_KEYUP is sent. The WM_KEYPRESSED message repeats during the hold, but it is less useful for game input.


According to the following documentation,

https://msdn.microsoft.com/en-us/library/windows/desktop/ms646280(v=vs.85).aspx

,"Because of the autorepeat feature, more than one WM_KEYDOWN message may be posted before a WM_KEYUP message is posted. The previous key state (bit 30) can be used to determine whether the WM_KEYDOWN message indicates the first down transition or a repeated down transition."

So both options are valid.

Further WM_KEYDOWN messages will only be posted at the auto-repeat rate; there will usually not be a new one in the queue every update.

Additionally, since those messages are tied to the auto-repeat functionality, they will only be sent for the last key pressed, and only as long as that key is held.

Don't clear your list between frames. Remove keys when you get the WM_KEYUP or when your application loses focus. Ignore redundant WM_KEYDOWN if your list already contains that key (you can use an flag array rather than a literal "list" that you add/remove from). Keyboard auto-repeat will only ever repeat the last key you started holding down.
It was requested that you show your message pump, because most likely you're only handling one message and then running your game loop.
You need to handle all messages that are pending and then run your game loop.

Or you need to not clear your list internally every frame.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Here is my loop.


//messageloop
while (msg.message != WM_QUIT)
{
	//send message to windowproc-function
	while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
	{
		TranslateMessage(&msg);
		DispatchMessageW(&msg);
	}

	//update
	if (!System::Update(Update))
	{
		//Exit the application on fail
		System::Exit(-1);
	}

	//render
	if (!System::Render(Render))
	{
		//Exit the application on fail
		System::Exit(-2);
	}

	//clear this frames key actions so next one's empty
	Input::keysDown.Clear();
	Input::keysUp.Clear();
}

Here is the messagehandling:


case WM_KEYDOWN:
	Input::keysDown.Add(System::CheckKey(wParam));
	return 0;

case WM_KEYUP:
	Input::keysUp.Add(System::CheckKey(wParam));
	return 0;

This topic is closed to new replies.

Advertisement