I was recently working on a database in which I was displaying a memo field in a text box on a form and was annoyed by the fact that the Mouse Wheel did not work to scroll though its’ content. Then, I started looking for a setting, a property, to enable it, but there wasn’t one!
Searching the Internet, I found examples to enable it, but they all used SendKeys. Any experienced programmer knows all to well that SendKeys is to be avoided at all cost, as they are unpredictable and thus very unreliable. So I went out searching for another solution.
This demo is the results of piecing together various sources of information.
As you will see by dissecting this Demo database, the entire thing is governed by one Standard Module housing a few APIs (GetFocus & SendMessage) and then the addition of a On Mouse Wheel event to the form containing the text box to enable wheel mouse scrolling on.
Hopefully, this can help someone else trying to make the mouse wheel work with a text box.
Disclaimer/Notes:
If you do not have Microsoft Access, simply download and install the freely available runtime version (this permits running MS Access databases, but not modifying their design):Microsoft Access 2010 Runtime
Microsoft Access 2013 Runtime
Microsoft Access 2016 Runtime
Microsoft 365 Access Runtime
In no event will Devhut.net or CARDA Consultants Inc. be liable to the client/end-user or any third party for any damages, including any lost profits, lost savings or other incidental, consequential or special damages arising out of the operation of or inability to operate the software which CARDA Consultants Inc. has provided, even if CARDA Consultants Inc. has been advised of the possibility of such damages.
Download
Feel free to download a copy (accdb x32/x64) by using the link provided below:
Download “Scrolling Text Box” Scrolling-Text-Box.zip – Downloaded 30760 times – 29.07 KBVersion History
| Version | Date | Summary of Changes |
|---|---|---|
| V1.000 | 2014-01-22 | Initial release |
| V1.001 | 2017-02-09 | Changed the Copyright so make it open to all to use (I had omitted this – Sorry!) Added Error Handling Minor code optimization/cleanup |
| V1.002 | 2019-02-07 | Simplified the overall code Adjusted the code to work with tab controls as well, per comments provided below |
| V1.003 | 2022-07-12 | Cleaned up API Declarations to use Microsoft’s version Added conditional compilation so it works in both 32 and 64-bit installations |
| V1.004 | 2022-10-13 | Create a Standard Behavior form Created a Main form to house both example as a comparison |
Hello Daniel, good morning. I just implemented your solution in my database and it helps me to solve the scroll problem in a textbox. Now, I wanted to comment on two things. The first is that, when it comes to a continuous form, the system doesn’t work well, because if I position myself in a textbox it will lower me correctly within it; but if I upload, it uploads the entire form. The second, and concatenated with the previous one, is that if you have solved that in a later version, then the one you have as a download is the initial version. Thank you very much.
Originally, when I developed this it was for a single form view.
That said, like with everything on this site, I am simply sharing information, things that have worked for me. I am in no way selling anything, nor making any promises with anything posted. The code is open/unlocked and you are always free to improve upon it to suit your needs. Unlike companies like Microsoft making millions, billions a year, this site is done for free! Thus, everything is provided ‘as is’ and it is up to you to take thing further should you choose to do so.
You’d can write this code in the “On Mouse Wheel” Event of the form that it has a CombBox or MemoBox. The code below uses SendKeys, which is reputed to be flaky (but it generally works OK most of times for most of us!) 🙂
Private Sub Form_MouseWheel(ByVal Page As Boolean, ByVal Count As Long) 'By Kasy Dim i As Long Dim s As String If Me.ActiveControl.Name = "Staff_Details" Then ' >>>> replace with name of Textbox or Memobox If Count > 0 Then For i = 1 To Count s = s & "{DOWN}" Next i Else For i = 1 To -Count s = s & "{UP}" Next i End If SendKeys s End If End SubEdited by admin to add code tags and indenting.
I haven’t tested it, but I still wouldn’t implement a SendKeys solution. In 20+ years of development, I’ve never needed to do so as there are always better approach. SendKeys is simply too dangerous to implement for enduser applications.
That said, thank you for sharing as others may appreciate it and not hold the same belief as me.
Side note, it should truly have proper error handling.
I have a copy of Office Pro Plus 2021 and it does not have an “on mouse wheel” event listed. Nor does the mouse scroll the text when in a text box. Hope this helps
Bit late to the party on this one, but in case it helps anyone else…
I found that the mouse wheel does scroll fine on my version of Access (365) without any additional code, but NOT with text boxes displaying Rich Text.
Your code however does work with both plain and Rich text
Thanks
Indeed, as of Access 2019, scrolling now works for plain text textboxes. Sadly, I wasn’t ever able to locate the corresponding MS365 build number, didn’t seem to be officially published at release by Microsoft. So it was buried in some update, but only MS knows which one.
Thank You for the help, the code is perfectly working on my forms.
I have office 2019.
it is not working without the code, is there a setting for the mouse scroll to activate or?
Thank you, your efforts are appreciated
No setting that I’m aware of. Perhaps an update, but I’m truly not sure. Check and insure you’re running the latest build.
I know its a quite outdated thread but i want to try to get an answer. Everything works fine, but by reaching the visible beginning or end of the TextBox you get an annoying windows-error tone. How to suppress it?
You could add
#If VBA7 Then
Public Declare PtrSafe Function MessageBeep Lib “user32” (ByVal wType As Long) As Long
#Else
Public Declare Function MessageBeep Lib “user32” (ByVal wType As Long) As Long
#End If
and then change the Form_MouseWhell to
Private Sub Form_MouseWheel(ByVal Page As Boolean, ByVal Count As Long)
On Error GoTo Error_Handler
Dim i As Long
If ActiveControl.ControlType = acTextBox Then
For i = 1 To Abs(Count)
‘ Try to absorb the beep
MessageBeep 0
SendMessage GetFocus, WM_VSCROLL, IIf(Count < 0, SB_LINEUP, SB_LINEDOWN), 0& Next End If Error_Handler_Exit: On Error Resume Next Exit Sub Error_Handler: MsgBox "The following error has occured" & vbCrLf & vbCrLf & _ "Error Number: " & Err.Number & vbCrLf & _ "Error Source: " & "Form_MouseWheel" & vbCrLf & _ "Error Description: " & Err.Description, _ vbOKOnly + vbCritical, "An Error has Occured!" Resume Error_Handler_Exit End Sub This has worked for me in the past. It's a bit of a hack, but if it works... Hopefully it will work for you as well.
Thank you. This doesnt avoid the beep but it delays it. Is there a possibilty to delay it longer or even better (only idea) to mute the windows volume by get focus on the textbox and restore volume on lost focus of the text box?
I have done it. It works this Way:
Option Compare Database
Option Explicit
‘ API zum Simulieren von Tastatur‑Events
Public Declare PtrSafe Sub keybd_event Lib “user32” ( _
ByVal bVk As Byte, _
ByVal bScan As Byte, _
ByVal dwFlags As Long, _
ByVal dwExtraInfo As LongPtr _
)
‘ Virtueller Key‑Code für Lautsprecher‑Mute
Public Const VK_VOLUME_MUTE As Byte = &HAD
‘ Flags für keybd_event
Public Const KEYEVENTF_KEYDOWN As Long = &H0000
Public Const KEYEVENTF_KEYUP As Long = &H0002
‘ Interner Toggle‑Status: haben wir selbst gemutet?
Public g_bIsMutedByAccess As Boolean
‘———————————————————-
‘ Master‑Mute ein‑/ausschalten
‘———————————————————-
Public Sub ToggleMasterMute()
Call keybd_event(VK_VOLUME_MUTE, 0, KEYEVENTF_KEYDOWN, 0)
Call keybd_event(VK_VOLUME_MUTE, 0, KEYEVENTF_KEYUP, 0)
g_bIsMutedByAccess = Not g_bIsMutedByAccess
End Sub
‘———————————————————-
‘ Nur stummschalten, wenn noch nicht stumm
‘———————————————————-
Public Sub MuteMasterVolume()
If g_bIsMutedByAccess = False Then ToggleMasterMute
End Sub
‘———————————————————-
‘ Nur wieder aktivieren, wenn wir vorher gemutet haben
‘———————————————————-
Public Sub UnmuteMasterVolume()
If g_bIsMutedByAccess = True Then ToggleMasterMute
End Sub
In the Form:
Private Sub Bemerkung_GotFocus()
On Error Resume Next
Call MuteMasterVolume
End Sub
Private Sub Bemerkung_LostFocus()
On Error Resume Next
Call UnmuteMasterVolume
End Sub
Private Sub Form_Unload(Cancel As Integer)
On Error Resume Next
Call UnmuteMasterVolume
End Sub
Works like a charm
Hope it helps other People
It’s a workaround, but not one I’d normally use. Imagine the employee listening to music at the desk and every time they enter a textbox the music mutes and then returns when they move to another control. You’re going to hear about it pretty fast.
Hello Daniel, Very informative post. However, i am a little confused why you dont rate or think the send key options / work arounds are safe or reliable? The only reason a send keys option wouldnt be safe or reliable is if one didnt code it correctly with the appropriate restrictions..
I have been coding in various forms for over 30 years and the only time that an error occurs or a risk is present when using sendkeys is if the developer didnt code it correctly or safely.
Using and implementing the windowsAPI adds alot more overhead. Using the API has increased the memory footprint and also added other causes for the module/function to fail or bork.
Instead of having something which uses only 6 lines of code within a subroutine you have blown the solution way out of proportion.
Having a subroutine that uses Sendkeys which basically sends an Up Key or a Down Key command isnt going to break anything… I would be interested to hear how you think this is not the case. Or use case scenarios where using Sendkeys that mimic an Up Arrow or Down Arrow key press present a risk…
How would code like this Present a risk?
Private Sub Form_MouseWheel(ByVal Page As Boolean, ByVal Count As Long) Select Case Count Case -2 SendKeys "{UP}" Case 2 SendKeys "{DOWN}" End Select End SubThere is no need for error handling because there are only two outcomes to the code, because it is a Case expression…..
The only adverse reaction to using this would be that the Cursor moves to the next control according to tab order if the default focus was on a normal control.
Regards,
Daniel
I avoid using SendKeys because they are inherently unreliable. Most experienced developers agree with this sentiment. The risk comes from the fact that if the application focus changes, if the user clicks somewhere else or another process steals focus while SendKeys is running, the commands may be sent to the wrong target, leading to unpredictable results. There are far more dependable methods available, and I prefer to use and recommend those to prevent unwanted behavior.
While some developers swear by SendKeys, I’ve seen many return later with problems they never anticipated. A quick search online will reveal numerous discussions echoing the same advice: don’t use SendKeys.
As for Windows API calls, I’m not concerned about the minimal overhead they introduce, especially considering the stability they provide. In my experience, well-written API-based code is far less prone to failure than SendKeys-based solutions.
If you are comfortable using SendKeys, no one will stop you. However, based on both my experience where I have seen SendKeys fail in production—and best practice principles, I choose not to rely on them.
Much of coding comes down to personal style and preferences and this is why I don’t use SendKeys, but that doesn’t mean you have to agree with me.