To add support for the new Microsoft Intellimouse Wheel in your OpenStep applications, just add the following code into your application somewhere.

This code operates by subclassing the undocumented class _NSWin32EventHandler, and posing as that class. Then if there is a WM_MOUSEWHEEL message on the event queue, it handles it directly. It sends the selector mouseWheeledUp: or mouseWheeledDown: to the first responder. I have included an implementation of mouseWheeledUp/Down: for NSScrollView.


#ifdef WIN32
#import <windows.h>
#endif

#import <AppKit/NSApplication.h>
#import <AppKit/NSScrollView.h>
#import <AppKit/NSClipView.h>

@interface NSResponder (MouseWheelEvents)
- (void) mouseWheeledUp:sender;
- (void) mouseWheeledDown:sender;
@end

#ifdef WIN32
// Some constants are missing from winuser.h, the NeXT header is too old
#define WM_MOUSEWHEEL 0x020A
#define WHEEL_DELTA 120 /* Value for rolling one detent */
#define WHEEL_PAGESCROLL (UINT_MAX) /* Scroll one page */
#define MOUSEEVENTF_WHEEL 0x0800 /* wheel button rolled */

@interface _NSWin32EventHandler : NSObject
- (void) handleMachMessage:(void*)msg;
@end

@interface Hacked_NSWin32EventHandler : _NSWin32EventHandler
@end

@implementation Hacked_NSWin32EventHandler
+ (void) load { [ self poseAsClass:[_NSWin32EventHandler class]]; }
- (void) handleMachMessage:(void*)msg
{
MSG event;
if (PeekMessage(&event, 0, WM_MOUSEWHEEL, WM_MOUSEWHEEL, PM_REMOVE)) {
if ( (short)HIWORD(event.wParam) > 0 ) {
short distance;
for (distance = HIWORD(event.wParam); distance > 0 ;
distance -= WHEEL_DELTA)
[NSApp sendAction:@selector(mouseWheeledUp:) to:0 from:0];
} else if ( (short)HIWORD(event.wParam) < 0 ) {
short distance;
for (distance = HIWORD(event.wParam); distance < 0 ;
distance += WHEEL_DELTA)
[NSApp sendAction:@selector(mouseWheeledDown:) to:0 from:0];
}
} else
[super handleMachMessage:msg];
}
@end
#endif

@implementation NSScrollView (MouseWheelEvents)
- (float) mouseWheelDistance
{
float line = [self lineScroll];
float page = [self documentVisibleRect].size.height - [self pageScroll];

page = page / 10.0;
if (line > page)
return line;
return page;
}

- (void) mouseWheeledUp:sender
{
NSClipView * clip;
NSPoint point;

if (![self hasVerticalScroller])
return;

clip = [self contentView];
point = [self documentVisibleRect].origin;
if ([clip isFlipped]) {
point.y -= [self mouseWheelDistance];
} else {
point.y += [self mouseWheelDistance];
}
point = [clip constrainScrollPoint:point];
[clip scrollToPoint:point];
[self reflectScrolledClipView:clip];
}

- (void) mouseWheeledDown:sender
{
NSClipView * clip;
NSPoint point;

if (![self hasVerticalScroller])
return;

clip = [self contentView];
point = [self documentVisibleRect].origin;
if ([clip isFlipped]) {
point.y += [self mouseWheelDistance];
} else {
point.y -= [self mouseWheelDistance];
}
point = [clip constrainScrollPoint:point];
[clip scrollToPoint:point];
[self reflectScrolledClipView:clip];
}

@end

« »