Sign in to follow this  
Starfox

Input event capture on Win32

Recommended Posts

Starfox    504
I'm trying to move a GLUT app away from GLUT for API change reasons and I'm trying to implement GLUT-like input handling on Win32. I already did it for OS X, and it was pretty straight forward, here's how it ended up:


[code]

NSEvent* event_handler(NSEvent* Event)
{
NSEventType EventType = [Event type];
NSPoint MouseLocation = [NSEvent mouseLocation];
int MouseX = MouseLocation.x;
//MouseY is inverted to match GLUT coordinate space
int MouseY = -MouseLocation.y;
if(EventType == NSLeftMouseDown)
{
MouseFunction(GLUT_LEFT_BUTTON, GLUT_DOWN, MouseX, MouseY);
}
if(EventType == NSLeftMouseUp)
{
MouseFunction(GLUT_LEFT_BUTTON, GLUT_UP, MouseX, MouseY);
}
if((EventType == NSMouseMoved) || (EventType == NSLeftMouseDragged))
{
MotionFunction(MouseX, MouseY);
}
if(EventType == NSKeyDown)
{
if([Event isARepeat] == NO)
{
NSString* EventString = [Event characters];
char ASCII[2] = { '\0', '\0' };
[EventString getCString: ASCII maxLength: 2 encoding: NSASCIIStringEncoding];
KeyboardFunction(ASCII[0], MouseX, MouseY);
}
//Consume keyboard events to prevent system "beep"
return nil;
}
return Event;
}

bool initialize_input_capture()
{
[NSEvent addLocalMonitorForEventsMatchingMask:NSAnyEventMask handler:^(NSEvent* Event) { return event_handler(Event); }];
return true;
}
[/code]

An NSEvent API call and a simple function. Now I'm trying to do the same thing with Win32 and I just can't seem to find a straightforward way to do so. Surprisingly, I've been a Win32 coder most of my life, my OS X experience is around ten weeks. One major issue is that I don't have access to the application's main window in Win32, and I can't seem to find a way to add a process-wide event monitor that easily. I also want to avoid something that polls the hardware as it might miss info when the framerate drops, not to mention its intrusion on the main loop. The solution I can think of currently is to create a hidden window and use a DirectInput object with that but that seems to be overkill and will at least go up to the KLOC range. Any recommendations?

Share this post


Link to post
Share on other sites
ApochPiQ    22999
I really, really, really question the sanity of your setup if you're porting code but you can't change the main window loop. The [i]correct[/i] solution is to modify the window procedure of the appropriate window to use Win32 Raw Input (please do not ever use DirectInput for mouse/keyboard operations).

However, if you are absolutely sure that you can't change that code - and I frankly can't even mentally contrive a situation wherein that might be true, and yet you're porting an entire app - then there's always [url="http://msdn.microsoft.com/en-us/library/ms644990(v=vs.85).aspx"]hooks[/url].

Share this post


Link to post
Share on other sites
Starfox    504
[quote name='ApochPiQ' timestamp='1310598936' post='4835047']
I really, really, really question the sanity of your setup if you're porting code but you can't change the main window loop. The [i]correct[/i] solution is to modify the window procedure of the appropriate window to use Win32 Raw Input (please do not ever use DirectInput for mouse/keyboard operations).

However, if you are absolutely sure that you can't change that code - and I frankly can't even mentally contrive a situation wherein that might be true, and yet you're porting an entire app - then there's always [url="http://msdn.microsoft.com/en-us/library/ms644990(v=vs.85).aspx"]hooks[/url].
[/quote]

The reasoning behind the desire to not intrude upon the application's main loop is that I'm not the owner of the end code - this is a piece of middleware, and I want the end-coder to be able to use it independently of their main loop setup. Sometimes there isn't an owner window to speak of - I was working on some DirectAudio code where I had to create my own hidden window in init() to cover the case where the user calls the API from, say, a console application.

Share this post


Link to post
Share on other sites
ApochPiQ    22999
Wait...

Why is your middleware trapping input events, then? That is absolutely [i]hideously disgusting[/i] behaviour. If I dropped your library into my app and it started screwing around with my input, I'd be incredibly pissed off.

If your library needs to handle input at all, then provide an interface and have your implementers [i]pass[/i] you the input.

Share this post


Link to post
Share on other sites
Starfox    504
The point of this part is to abstract the platform input handling - I can safely assume that the end user isn't using another method to capture input. Think of it as a non-mainloop-takingover version of glut Keyboard / Mouse / Motion func. Given that I'm the one responsible for abstracting away platform input, what do you think I should do?

Share this post


Link to post
Share on other sites
ApochPiQ    22999
You can't have it both ways.

Option one is that you control the platform, and your library is the minimum level of abstraction upon which the client builds - i.e. the client does not screw with the "main loop" or whatever else. You provide the services and the client builds on top.

The other option is that you let the client code control the "main loop" (in whatever form that happens to take) and passes raw input to you, which you then forward back out using a mapping interface or something similar to [url="http://www.gamedev.net/blog/355/entry-2250186-designing-a-robust-input-handling-system-for-games/"]this[/url].


What you're suggesting is a fundamental design contradiction. You can't do something low-level like handle platform-specific input gathering [i]and[/i] be completely independent of low-level platform specifics.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this