Jump to content
  • Advertisement
Sign in to follow this  
hanhau

Handling Messages from win32api window to InputManager

This topic is 775 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 Guys,

I am currently working on an InputManager, wich should be able to track activities and process Input Events.
I would like to support Mouse, Keyboard and Joystick/Gamepad Input.
This is how it works (prototype):

    -> check for input devices states and events
    -> add them into a stack
    -> check for registered actions with the events
    -> execute this actions

So I could create the Action "JUMP" wich will be bound on the "space" key and another key like "e".
Then it checks for inputs and when the input is "space", it will look up in the actions and execute "JUMP".

So far soo good, now I wanna get the Messages from my window (winapi window).

I saw that you can create WindowHooks, but I saw just ones for Mouse and Keyboard.
So I thought just putting the message handling in the Main-Window-Procedure (LRESULT CALLBACK WndProc(....)), so
I can have the support for all Input Device Types.

Is that the way it should be made ? I wanna achieve a fast Input handling, or at least as fast as possible without
too much effort, maybe more, when it is worth it. I dont ask for code, hell no. But some tips or maybe own thoughts and
stories how you did it would be nice to get.

Thank you very much !
 

Share this post


Link to post
Share on other sites
Advertisement

i run the windows message pump when need as needed to get mouse input. a get_mouse() routine is used to get mouse position and button presses as of the last call to run the message pump. i use getasynckeystate to poll the keyboard. i have no need at this time to support joysticks or game controllers.

 

but this is not what most folks do. 

 

this just runs the message pump as needed for mouse input, which just happens to be often enough windows doesn't think you've become unresponsive. running the message pump can be encapsulated in the get_mouse call, meaning you can by and large write the game as a regular non-windows app, and forget about message ques and all that stuff.

 

and this just uses a low level windows api call to get hardware interrupt driven keyboard input. i think most folks use the windows message queue for that. but i started making games before windows. and hardware interrupt driven keyboard input was a standard component of all games. when i switched to win32 PE executable games, getasynckeystate was the rough equivalent - and thus the natural choice. besides, going from hardware interrupt driven to windows message queue would be a step backwards in performance.

 

i'm sure someone else here can clue you in on the "usual" way to do these things.

Share this post


Link to post
Share on other sites

I have an implementation of input handling in my engine too but different from the usual usement of WM_Message I use HID to achieve this as it is lot faster (~0.0001 ms) to process the input that other parts of the game could handle it and supports any kind of hardware since the winmm.dll headers just support Gamepad polling.

 

I event dont have a difference between keys, buttons and axis when "handling" the input. Each WM_INPUT message delivers an input report that needs to be preparsed first to get the kind of input (Mouse, Keyboard, Gamepad) and the device handle that input was send from (supports multiple Mouse, Keyboard, Gamepad). After that the WM_INPUT message gets passed to the device and parsed by the devices own HID report data and stored in a queue (instance or global managed, both possible)

 

Inside the queue lay all input reports received that may be one or multiple ones including a union that creates the input id.

struct Stat
		{
			union
			{
				uint32 Code;
				struct
				{
					uint16 Type;
					union
					{
						uint16 Id;
						uint16 ScanCode;
					};
				};
			};
			union
			{
				struct
				{ 
					uint16 KeyStat;
					uint16 KeyCode;
				};
				uint16 Value;
			};
		};

Where Type is the device type the input comes from and id is the button/axis/key index.

Receiving (or polling the input report over the global queue) inputs for certain action works over the Id field

so for your JUMP action example it wouldnt be bound to the "Space" key rather than to the Id { Keyboard, Button }.

This makes it much easier to traverse a list or map and call the according action function,

 

The message queue is processed async in a worker pool for achiving better framerates instead of the main loop.

For multiple device support you may have an own queue in each attached device rather than a global message loop.

Edited by Shaarigan

Share this post


Link to post
Share on other sites

I have an implementation of input handling in my engine too but different from the usual usement of WM_Message I use HID to achieve this as it is lot faster (~0.0001 ms) to process the input that other parts of the game could handle it and supports any kind of hardware since the winmm.dll headers just support Gamepad polling.

 

I event dont have a difference between keys, buttons and axis when "handling" the input. Each WM_INPUT message delivers an input report that needs to be preparsed first to get the kind of input (Mouse, Keyboard, Gamepad) and the device handle that input was send from (supports multiple Mouse, Keyboard, Gamepad). After that the WM_INPUT message gets passed to the device and parsed by the devices own HID report data and stored in a queue (instance or global managed, both possible)

 

Inside the queue lay all input reports received that may be one or multiple ones including a union that creates the input id.

struct Stat
		{
			union
			{
				uint32 Code;
				struct
				{
					uint16 Type;
					union
					{
						uint16 Id;
						uint16 ScanCode;
					};
				};
			};
			union
			{
				struct
				{ 
					uint16 KeyStat;
					uint16 KeyCode;
				};
				uint16 Value;
			};
		};

Where Type is the device type the input comes from and id is the button/axis/key index.

Receiving (or polling the input report over the global queue) inputs for certain action works over the Id field

so for your JUMP action example it wouldnt be bound to the "Space" key rather than to the Id { Keyboard, Button }.

This makes it much easier to traverse a list or map and call the according action function,

 

The message queue is processed async in a worker pool for achiving better framerates instead of the main loop.

For multiple device support you may have an own queue in each attached device rather than a global message loop.

That is what I also found now. Using Raw Informations seems to be more performant and efficient, altough I dont know
yet how to manage multiple connected gamepads or joysticks. But it just needs some reading go get comfortable with it I guess.
That shouldnt be now a problem.

This helped me a LOT ! Also with designing the whole thing a little bit more future proof for other projects.
Thanks !

Share this post


Link to post
Share on other sites

 


I dont know yet how to manage multiple connected gamepads or joysticks

 

 

I use "handles" to identify my devices based on the HID input report handle returned as void pointer. To manage multiple gamepads for multiple players in my solution the input report array is passed into a device based queue (handled from the device class) so you just need to know player to gamepad matching but thats it, anything else works as described above.

 

To handle multiple gamepads for a single player just add them as normaly to get raw input by using RegisterRawInputDevice on a window (in my solution I also add the first device that is registered as default mouse or keyboard)

RAWINPUTDEVICE rdv = RAWINPUTDEVICE();
		rdv.hwndTarget = (HWND)handle;
		rdv.usUsage = device.Usage;
		rdv.usUsagePage = device.UsagePage;
		rdv.dwFlags = 0;

		bool result = boolean_cast(RegisterRawInputDevices(&rdv, 1, sizeof(RAWINPUTDEVICE)));
		{
			if(!defaultMouse && device.Type == InputDevice::Mouse)
				NN::memcpy(&defaultMouse, &device, sizeof(InputDevice));
			if(!defaultKeyboard && device.Type == InputDevice::Keyboard)
				NN::memcpy(&defaultKeyboard, &device, sizeof(InputDevice));
		}

		return result;

Then you could handle WM_INPUT for them all at once

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!