Input filtering in Win32

Started by
5 comments, last by adeyblue 11 years, 4 months ago
This has been winding me up for most of the day and I can find little to no help about it.

I'm working on a project (https://github.com/MiniAl/ocarina) and I decided to start with a simple input mechanism to grab Win32 messages from the queue and process them separately; I'm trying to treat the game as a blunt information system with segregated input, processing, and output.

So I've spent time doing some research about message pumps and I understand I can have multiple Get-Dispatch loops.

However; I want to filter the received messages for just input. That's fine PeekMessage has range filtering on it.

Except I want all input (WM_MOUSEMOVE, WM_INPUT, WM_KEYDOWN) so that I'm flexible in certain situations. I don't really want to just call PeekMessage 4 or 5 times. Right now I'm concerntrating on just WM_INPUT.

The next thing I found was the filtering that can be requested as a flag. [source lang="cpp"]PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_INPUT)[/source]I was pretty certain this is what I needed but when implementing the loop it never tests true. It's like the window never receives input at all.[source lang="cpp"]while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_INPUT))
InputProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);

while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
DispatchMessage(&msg);[/source]The first loop grabs all the input data and then the second loop continues all the other messages.

I've been fiddling with break points and numerous 'printf' hacks and the first loop never tests true. I can't understand why.

Also, the expression [source lang="cpp"]PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | ~PM_QS_INPUT)[/source]brings the program to a halt. The statement makes logical sense but I assume there's an implementation detail I am missing.

Can anyone with previous experiences or knowledge throw me a bone?
Advertisement
I haven't ever used the function, but reading the APIs, PM_QS_INPUT has a value of 0x04070000, PM_QS_PAINT has a value of 0x00200000, PM_QS_SENDMESSAGE has a value of 0x00400000, and PM_QS_POSTMESSAGE has a value of 0x00980000.

The default is to process all messages, unless you specify with one of these flags, meaning the upper 16 bits is likely zero in this case. Since ~PM_QS_INPUT does not represent a mask that combines all of the other flags, it may invoke behavior undefined by their documentation. If you want to specify all other types of input but PM_QS_INPUT (which is what I think you are trying to do), you should specify a OR'ed mask of all of the others. I know it's possible that they might add a new constant, but they were very specific with what they will accept, so first make sure that you abide by these rules. If it still comes to a halt, then it is worth investigating.

Also, try to make sure that you are calling whatever function is necessary to update the queue before attempting to read from it. Many input systems will only poll and gather events when you call a function that makes it check its internal state for changes, so make sure that there isn't some function that you need to call first to populate the event queue before you start reading through it.
[source lang="cpp"]while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_PAINT | PM_QS_...))
InputProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);[/source]Still makes the program hang. It never receives input.

Why does a test for input never receive any? A normal, unconcerned loop pulls input messages from the loop so they are there. Am I using PeekMessage incorrectly? I've read its entire MSDN page.
http://stackoverflow.com/questions/1133507/is-there-a-function-like-peekmessage-that-doesnt-process-messages

According to the information in this link, it may mean that PeekMessage might be processing messages without retrieving them, unless you install hooks for events or something of the like. Perhaps there's a better way to do what you are trying to do?
Does this not imply that there's no need to call DispatchMessage in a PeekMessage loop?

There probably is; I've begun wrapping this input part so I can just keep working and come back to it later but right now it is really, really, really irritating that I don't understand it.
I'm not quite sure; someone familiar with the API should probably shed more light on this. I don't really do much Windows programming, as it isn't my primary OS.

while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_PAINT | PM_QS_...))
InputProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
Still makes the program hang. It never recieves input
[/quote]
Nothing you can give PeekMessage will make it hang, so without being able to see the code it's probably one of a couple things:
1. Like in the first post, invalid flags are being passed to the only / all PeekMessages and the window hangs because no messages are being retrieved at all. You'd also see that if you run the message pump on a different thread to the one that created the window.
2. There's a rogue Sleep / WaitForSingleObject that rarely returns
3. It's working fine except that InputProc isn't calling DefWindowProc for some window or keyboard messages so certain things it does for you (like letting you double click the title bar to move the window or pressing Alt to start the window menu) aren't happening

On a stylistic note, it's not the best idea to call your custom message dispatching function the same thing as the Windows one, especially when they share the same signature. At least, I thought the DispatchMessage in the snippets here was the Windows function before I checked your repo. Or maybe you changed back, and it is!


Does this not imply that there's no need to call DispatchMessage in a PeekMessage loop?
[/quote]
You don't have to call it, but even if you only explicitly create one window things like COM or plugins (if you allow those) can create other windows that run on the same thread. Without a (Windows) DispatchMessage, any messages picked off the queue intended for them will never make it to their WndProc, unless you do it manually. It also does other stuff like translate unicode messages for non-unicode WndProcs and vice versa. It's not anything you couldn't do yourself though.

This topic is closed to new replies.

Advertisement