Input filtering in Win32
#1 Members - Reputation: 286
Posted 13 December 2012 - 05:54 PM
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?
#2 Members - Reputation: 878
Posted 13 December 2012 - 10:10 PM
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.
Edited by Ectara, 13 December 2012 - 10:12 PM.
#3 Members - Reputation: 286
Posted 14 December 2012 - 08:40 PM
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.
#4 Members - Reputation: 878
Posted 14 December 2012 - 09:53 PM
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?
#5 Members - Reputation: 286
Posted 14 December 2012 - 10:31 PM
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.
#7 Members - Reputation: 515
Posted 15 December 2012 - 10:25 PM
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: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
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!
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.Does this not imply that there's no need to call DispatchMessage in a PeekMessage loop?
Edited by adeyblue, 15 December 2012 - 10:28 PM.






