Input event capture on Win32

Started by
4 comments, last by ApochPiQ 12 years, 9 months ago
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:




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;
}


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?
Holy crap I started a blog - http://unobvious.typepad.com/
Advertisement
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 correct 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 hooks.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]


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 correct 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 hooks.


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.
Holy crap I started a blog - http://unobvious.typepad.com/
Wait...

Why is your middleware trapping input events, then? That is absolutely hideously disgusting 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 pass you the input.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

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?
Holy crap I started a blog - http://unobvious.typepad.com/
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 this.


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

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This topic is closed to new replies.

Advertisement