Interfaceing with the intellimouse

Level:
Level2

Starting in late 1996, Microsoft began deliving the new Intellimouse. This mouse is notable, because it comes with a small wheel located between the two buttons. This wheel is generally used by applications to allow the user to scroll up and down documents.

As this style of mouse becomes more common, it will become increasingly important to provide some degree of support for the Intellimouse wheel. Already Gateway 2000 is shipping the Intellimouse with new PCs, and doubtlessly other manufacturers are or will ship the Intellimouse or clones which emulates it's functionality.

VB6 does not directly support the Intellimouse. Microsoft does, however, provide documentation for accessing the mouse in Active Visual Basic 5.0 (Eddon & Eddon, 1997 Microsoft Press, isbn 1-57231-512-1). The example provided by this tome details how to create an ActiveX control which traps Intellimouse wheel events.

The example contained in this web document is geared for inclusion into a standard EXE project. As a result, it should work well. I choose this approach because a simple example without the concerns of ActiveX programming is needed.

Create A Standard Form (Form1) than add this code to it:

Option Explicit
Private Sub Form_Load()
	IMWheel_Hook
End Sub
Public Sub WheelMoved(ByVal delta As Long, _
	X As Long, Y As Long)
	Debug.Print delta, X, Y
End Sub
Private Sub Form_Unload(Cancel As Integer)
	IMWheel_Unhook
End Sub

Add a Module to your application (Module1) than add this code to it:

Option Explicit
' 		
#If Win32 Then
Public Type POINTAPI
	X As Long
	Y As Long
End Type
' 		
Public Type MSG
	hwnd As Long
	message As Long
	wParam As Long
	lParam As Long
	time As Long
	pt As POINTAPI
End Type
' 		
Public Declare Function CallNextHookEx& Lib "user32" (ByVal hHook As Long, _
	ByVal nCode As Long, ByVal wParam As Integer, lParam As Any)
Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare Function RegisterWindowMessage& Lib "user32" Alias _
	"RegisterWindowMessageA" (ByVal lpString As String)
Public Declare Function SetWindowsHookEx& Lib "user32" Alias _
	"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _
	ByVal hmod As Long, ByVal dwThreadId As Long)
Public Declare Function UnhookWindowsHookEx& Lib "user32" _
	(ByVal hHook As Long)
' 		
#End If 'WIN32 declares and types
' 		
Public Const WH_GETMESSAGE = 3
Public Const MSH_MOUSEWHEEL = "MSWHEEL_ROLLMSG"
' 		
Public IMWHEEL_MSG As Long
Public HWND_HOOK As Long
Public Function IMWheel(ByVal nCode As Long, ByVal wParam As Long, _
	lParam As MSG) As Long
' 		
	If lParam.message = IMWHEEL_MSG Then
		Form1.WheelMoved lParam.wParam, lParam.pt.X, lParam.pt.Y
	End If
	IMWheel = CallNextHookEx(HWND_HOOK, nCode, wParam, lParam)
End Function
Public Function IMWheel_Hook() As Long
	IMWHEEL_MSG = RegisterWindowMessage(MSH_MOUSEWHEEL)
	HWND_HOOK = SetWindowsHookEx(WH_GETMESSAGE, _
		AddressOf IMWheel, 0, GetCurrentThreadId)
End Function
Public Sub IMWheel_Unhook()
	UnhookWindowsHookEx HWND_HOOK
End Sub

Because this codes hooks into the windows messaging system, you should not use the IDE's STOP button to terminate the execution of your code. Closing the form normally is mandatory. Debugging will become difficult once you have hooked the mouse messages, so I recommend adding Intellimouse support after the bulk of your programming work has been completed. As with any serious API programming tasks, you should save your project before execution.

I do not know if it will apply to this particular subclassing method, but the Visual Basic Programmer's Journal's website (DevX) reportedly has a DLL that can be added to a project at runtime that will help you work around limitations related to subclassing.

One of the nice features of the intellimouse hook, is that it returns both the X and Y coordinates (in pixels) of where the mouse was at when the wheel was moved. This means that, with a little API work, you can perform different actions based upon where the mouse is located. You should be able to add scrolling support to multiple controls, though I recommend defining a default control in the event that the mouse is not located over anything that can be scrolled.

NOTE: You may not have to do all this to have the intellimouse work with recent Windows OSes (such as XP) let me know if it is of use to you.

Originally Written By Tim Kilgore - modified some for this site.

If you enjoyed this post, subscribe for updates (it's free)