ACC2000: How to Detect and Prevent the Mouse Wheel from Scrolling Through Records in a Form


Advanced: Requires expert coding, interoperability, and multiuser skills.


This article applies to a Microsoft Access database (.mdb) and to a Microsoft Access project (.adp).


Summary


Microsoft Access does not provide a method for preventing users from using the mouse wheel to scroll through records on a form. This article shows you how to programmatically prevent users from using the mouse wheel to scroll through records on a form.


NOTE: If the code in this article does not function as expected, you may have to install the latest Microsoft IntelliPoint or third-party mouse software. To download the IntelliPoint software, visit the following Microsoft Web site:

More Information


Microsoft provides programming examples for illustration only, without warranty either expressed or implied. This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose. This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures. Microsoft support engineers can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements. By default, users can roll the mouse wheel to scroll through a series of records in a Microsoft Access form. If you want to prevent this, you can use the Win32 API to subclass your forms and to ignore mouse wheel messages sent to the form. There are two approaches for doing this. The first approach is to use Microsoft Visual Basic or Microsoft Visual C++ to create an ActiveX DLL that subclasses your Microsoft Access forms, and then to reference that DLL from your Microsoft Access application. A second method is to write all the code within Microsoft Access itself without using an ActiveX DLL. Because of problems with subclassing windows after loading the Microsoft Office Visual Basic Editor, Microsoft highly recommends that you use Microsoft Visual Basic or Microsoft Visual C++ to create an ActiveX DLL, and that you then reference the DLL from your Microsoft Access application.

Creating the MouseWheel Event by Using a Visual Basic ActiveX DLL

  1. Start Microsoft Visual Basic 6.0.
  2. Create a new ActiveX DLL project, and then open it.
  3. Add the following code to the class module window that appears:
    Option Compare Text
    Option Explicit

    Private frm As Object
    Private intCancel As Integer
    Public Event MouseWheel(Cancel As Integer)

    Public Property Set Form(frmIn As Object)
    Set frm = frmIn
    End Property

    Public Property Get MouseWheelCancel() As Integer
    MouseWheelCancel = intCancel
    End Property

    Public Sub SubClassHookForm()
    lpPrevWndProc = SetWindowLong(frm.hwnd, GWL_WNDPROC, _
    AddressOf WindowProc)
    Set CMouse = Me
    End Sub

    Public Sub SubClassUnHookForm()
    Call SetWindowLong(frm.hwnd, GWL_WNDPROC, lpPrevWndProc)
    End Sub

    Public Sub FireMouseWheel()
    RaiseEvent MouseWheel(intCancel)
    End Sub
  4. Set the class module properties as follows:

    Class Module: CMouseWheel
    -------------------------
    Name: CMouseWheel
    Instancing: 5 - MultiUse
  5. Add a standard module to the project, and then add the following code:
    Option Compare Text
    Option Explicit

    Public CMouse As CMouseWheel
    Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
    (ByVal hwnd As Long, _
    ByVal nIndex As Long, _
    ByVal dwNewLong As Long) As Long

    Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
    (ByVal lpPrevWndFunc As Long, _
    ByVal hwnd As Long, _
    ByVal msg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long

    Public Const GWL_WNDPROC = -4
    Public Const WM_MouseWheel = &H20A
    Public lpPrevWndProc As Long
    Public Function WindowProc(ByVal hwnd As Long, _
    ByVal uMsg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long
    Select Case uMsg
    Case WM_MouseWheel
    CMouse.FireMouseWheel
    If CMouse.MouseWheelCancel = False Then
    WindowProc = CallWindowProc(lpPrevWndProc, hwnd, uMsg, wParam, lParam)
    End If

    Case Else
    WindowProc = CallWindowProc(lpPrevWndProc, hwnd, uMsg, wParam, lParam)
    End Select
    End Function
  6. On the View menu, click Project Explorer to view the Project Explorer.
  7. Select the project node at the very top of the Project Explorer.
  8. On the View menu, click Properties to view the property sheet for the project.
  9. Set the project's Name property to MouseWheel.
  10. On the File menu, click Save Project.
  11. Save the project files as basSubClassWindow.bas, CMouseWheel.cls, and MouseWheel.vbp respectively.
  12. On the File menu, click Make MouseWheel.dll, and then click OK to make the DLL.
  13. Quit Microsoft Visual Basic.
  14. Start Microsoft Access, and then open the sample database Northwind.mdb.
  15. Open the Customers form in Design view.
  16. On the View menu, click Code to display the module of the form in the Visual Basic Editor.
  17. On the Tools menu, click References.
  18. Click to select the check box next to MouseWheel to select the reference. If you do not see this reference listed, click the Browse button, click MouseWheel.DLL in the folder that you saved it to in step 12, and then click Open.
  19. Click OK to close the References dialog box.
  20. Add the following code to the module of the form:
    Option Compare Database
    Option Explicit

    Private WithEvents clsMouseWheel As MouseWheel.CMouseWheel

    Private Sub Form_Load()
    Set clsMouseWheel = New MouseWheel.CMouseWheel
    Set clsMouseWheel.Form = Me
    clsMouseWheel.SubClassHookForm
    End Sub

    Private Sub Form_Close()
    clsMouseWheel.SubClassUnHookForm
    Set clsMouseWheel.Form = Nothing
    Set clsMouseWheel = Nothing
    End Sub

    Private Sub clsMouseWheel_MouseWheel(Cancel As Integer)
    MsgBox "You cannot use the mouse wheel to scroll records."
    Cancel = True
    End Sub
  21. On the File menu, click Close and Return to Microsoft Access.
  22. Save the form, and then close it.
  23. Open the Customers form in Form view.
  24. Roll the mouse wheel.
Note that you receive the message:

You cannot use the mouse wheel to scroll records.
Also note that the current record has not changed, indicating that the mouse wheel message was not processed by Microsoft Access.

Creating the MouseWheel Event Completely Within Microsoft Access

WARNING: If possible, you should use the method listed in the "Creating the MouseWheel Event by Using a Visual Basic ActiveX DLL" section earlier in this article. You can use the method discussed in this section only in a situation where the users of your application will not be loading the Visual Basic Editor within Microsoft Access, such as in a Microsoft Access run-time application. If you implement this solution and your users open the Visual Basic Editor, the code in this section will cause Microsoft Access to stop responding. Additionally, you must quit and restart Microsoft Access before testing this code if you have loaded the Visual Basic Editor at least once during the Microsoft Access session. Microsoft highly recommends that you save your work often and that you keep current backups of your database if you use this approach.

The approach demonstrated in this section shows how to use a custom class module to create a custom event named MouseWheel, which you can use in your forms to detect when the user has rolled the mouse wheel. This custom event exposes a Cancel argument that you can use to prevent the mouse wheel roll message from being intercepted by Microsoft Access, thereby preventing record scrolling in the form.

To create the custom procedures, follow these steps:

  1. CAUTION: If you follow the steps in this example, you modify the sample database Northwind.mdb. You may want to back up the Northwind.mdb file and follow these steps on a copy of the database.

  2. Start Microsoft Access.
  3. Open the sample database Northwind.mdb.
  4. On the Insert menu, click Module to create a new module in the Visual Basic Editor.
  5. Add the following code to the module:
    Option Compare Database
    Option Explicit

    Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
    (ByVal hwnd As Long, _
    ByVal nIndex As Long, _
    ByVal dwNewLong As Long) As Long

    Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
    (ByVal lpPrevWndFunc As Long, _
    ByVal hwnd As Long, _
    ByVal msg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long


    Public Const GWL_WNDPROC = -4
    Public Const WM_MouseWheel = &H20A
    Public lpPrevWndProc As Long
    Public CMouse As CMouseWheel

    Public Function WindowProc(ByVal hwnd As Long, _
    ByVal uMsg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long

    'Look at the message passed to the window. If it is
    'a mouse wheel message, call the FireMouseWheel procedure
    'in the CMouseWheel class, which in turn raises the MouseWheel
    'event. If the Cancel argument in the form event procedure is
    'set to False, then we process the message normally, otherwise
    'we ignore it. If the message is something other than the mouse
    'wheel, then process it normally
    Select Case uMsg
    Case WM_MouseWheel
    CMouse.FireMouseWheel
    If CMouse.MouseWheelCancel = False Then
    WindowProc = CallWindowProc(lpPrevWndProc, hwnd, uMsg, wParam, lParam)
    End If


    Case Else
    WindowProc = CallWindowProc(lpPrevWndProc, hwnd, uMsg, wParam, lParam)
    End Select
    End Function
  6. On the File menu, click Save <project name>. Save the module as basSubClassWindow.
  7. On the Insert menu, click Class Module.
  8. Add the following code to the class module:
    Option Compare Database
    Option Explicit

    Private frm As Access.Form
    Private intCancel As Integer
    Public Event MouseWheel(Cancel As Integer)

    Public Property Set Form(frmIn As Access.Form)
    'Define Property procedure for the class which
    'allows us to set the Form object we are
    'using with it. This property is set from the
    'form class module.
    Set frm = frmIn
    End Property

    Public Property Get MouseWheelCancel() As Integer
    'Define Property procedure for the class which
    'allows us to retrieve whether or not the Form
    'event procedure canceled the MouseWheel event.
    'This property is retrieved by the WindowProc
    'function in the standard basSubClassWindow
    'module.

    MouseWheelCancel = intCancel
    End Property

    Public Sub SubClassHookForm()
    'Called from the form's OnOpen or OnLoad
    'event. This procedure is what "hooks" or
    'subclasses the form window. If you hook the
    'the form window, you must unhook it when completed
    'or Access will crash.

    lpPrevWndProc = SetWindowLong(frm.hwnd, GWL_WNDPROC, _
    AddressOf WindowProc)
    Set CMouse = Me
    End Sub

    Public Sub SubClassUnHookForm()
    'Called from the form's OnClose event.
    'This procedure must be called to unhook the
    'form window if the SubClassHookForm procedure
    'has previously been called. Otherwise, Access will
    'crash.

    Call SetWindowLong(frm.hwnd, GWL_WNDPROC, lpPrevWndProc)
    End Sub

    Public Sub FireMouseWheel()

    'Called from the WindowProc function in the
    'basSubClassWindow module. Used to raise the
    'MouseWheel event when the WindowProc function
    'intercepts a mouse wheel message.
    RaiseEvent MouseWheel(intCancel)
    End Sub
  9. On the File menu, click Save <project name>. Save the class module as CMouseWheel.
  10. Open the Customers form in Design view.
  11. On the View menu, click Code to view the class module of the form.
  12. Add the following code to the class module of the form:
    Option Compare Database
    Option Explicit

    'Declare a module level variable as the custom class
    'and give us access to the class's events
    Private WithEvents clsMouseWheel As CMouseWheel

    Private Sub Form_Load()
    'Create a new instance of the class,
    'and set the class's Form property to
    'the current form
    Set clsMouseWheel = New CMouseWheel
    Set clsMouseWheel.Form = Me

    'Subclass the current form by calling
    'the SubClassHookForm method in the class
    clsMouseWheel.SubClassHookForm
    End Sub

    Private Sub Form_Close()
    'Unhook the form by calling the
    'SubClassUnhook form method in the
    'class, and then destroy the object
    'variable

    clsMouseWheel.SubClassUnHookForm
    Set clsMouseWheel.Form = Nothing
    Set clsMouseWheel = Nothing
    End Sub

    Private Sub clsMouseWheel_MouseWheel(Cancel As Integer)
    'This is the event procedure where you can
    'decide what to do when the user rolls the mouse.
    'If setting Cancel = True, we disable the mouse wheel
    'in this form.

    MsgBox "You cannot use the mouse wheel to scroll through records."
    Cancel = True
    End Sub
  13. On the File menu, click Close and Return to Microsoft Access.
  14. Save the form, and then close it.

    NOTE: Do not open the form in Form view at this time. If you do, Microsoft Access will stop responding because the Visual Basic Editor has been loaded.
  15. Quit Microsoft Access.
  16. Restart Microsoft Access, and open the sample database Northwind.mdb.
  17. Open the Customers form in Form view.
  18. Roll the mouse wheel.
Note that you receive the message:
You cannot use the mouse wheel to scroll through records.
Also note that the current record has not changed, indicating that the mouse wheel message was not processed by Microsoft Access.