Making Combobox Scrollable within frame on Userform

gagey

New Member
Joined
Sep 20, 2016
Messages
10
Hello: I found this amazing code from Peter Thorton to make listbox's and combobox's scrollable. I am using Excel 2016 and it works fine on my combobox's that sit directly on a form, however it does not work for my combobox's that sit on a frame on the form. I thought it would be quite simple to adapt the code to work for these combobox's, but have been unsuccessful. Can someone please advise me how I would adapt my code so that the combobox's sitting in a frame on a form are also scrollable. Any assistance is greatly appreciated!

Peter's Code:

OK, now I know which code worked for you. Could you also clarify if you tried the code you found, which as written didn't work, but with the corrections I suggested.
The following should scroll both ComboBox and ListBox controls with the mouse wheel.
Put one ComboBox and two ListBox's on a form. Paste the following into the Userform module and a Normal module as indicated
Code:
'''''' normal module code

Option Explicit

Private Type POINTAPI
        X As Long
        Y As Long
End Type

Private Type MOUSEHOOKSTRUCT
        pt As POINTAPI
        hwnd As Long
        wHitTestCode As Long
        dwExtraInfo As Long
End Type

Private Declare Function FindWindow Lib "user32" _
                                        Alias "FindWindowA" ( _
                                                        ByVal lpClassName As String, _
                                                        ByVal lpWindowName As String) As Long

Private Declare Function GetWindowLong Lib "user32.dll" _
                                        Alias "GetWindowLongA" ( _
                                                        ByVal hwnd As Long, _
                                                        ByVal nIndex As Long) As Long

Private Declare Function SetWindowsHookEx Lib "user32" _
                                        Alias "SetWindowsHookExA" ( _
                                                        ByVal idHook As Long, _
                                                        ByVal lpfn As Long, _
                                                        ByVal hmod As Long, _
                                                        ByVal dwThreadId As Long) As Long

Private Declare Function CallNextHookEx Lib "user32" ( _
                                                        ByVal hHook As Long, _
                                                        ByVal nCode As Long, _
                                                        ByVal wParam As Long, _
                                                        lParam As Any) As Long

Private Declare Function UnhookWindowsHookEx Lib "user32" ( _
                                                        ByVal hHook As Long) As Long

'Private Declare Function PostMessage Lib "user32.dll" _
'                                         Alias "PostMessageA" ( _
'                                                         ByVal hwnd As Long, _
'                                                         ByVal wMsg As Long, _
'                                                         ByVal wParam As Long, _
'                                                         ByVal lParam As Long) As Long

Private Declare Function WindowFromPoint Lib "user32" ( _
                                                        ByVal xPoint As Long, _
                                                        ByVal yPoint As Long) As Long

Private Declare Function GetCursorPos Lib "user32.dll" ( _
                                                        ByRef lpPoint As POINTAPI) As Long

Private Const WH_MOUSE_LL As Long = 14
Private Const WM_MOUSEWHEEL As Long = &H20A
Private Const HC_ACTION As Long = 0
Private Const GWL_HINSTANCE As Long = (-6)

'Private Const WM_KEYDOWN As Long = &H100
'Private Const WM_KEYUP As Long = &H101
'Private Const VK_UP As Long = &H26
'Private Const VK_DOWN As Long = &H28
'Private Const WM_LBUTTONDOWN As Long = &H201

Private mLngMouseHook As Long
Private mListBoxHwnd As Long
Private mbHook As Boolean
Private mCtl As MSForms.Control
Dim n As Long

Sub HookListBoxScroll(frm As Object, ctl As MSForms.Control)
Dim lngAppInst As Long
Dim hwndUnderCursor As Long
Dim tPT As POINTAPI
     GetCursorPos tPT
     hwndUnderCursor = WindowFromPoint(tPT.X, tPT.Y)
     If Not frm.ActiveControl Is ctl Then
             ctl.SetFocus
     End If
     If mListBoxHwnd <> hwndUnderCursor Then
             UnhookListBoxScroll
             Set mCtl = ctl
             mListBoxHwnd = hwndUnderCursor
             lngAppInst = GetWindowLong(mListBoxHwnd, GWL_HINSTANCE)
             ' PostMessage mListBoxHwnd, WM_LBUTTONDOWN, 0&, 0&
             If Not mbHook Then
                     mLngMouseHook = SetWindowsHookEx( _
                                                     WH_MOUSE_LL, AddressOf MouseProc, lngAppInst, 0)
                     mbHook = mLngMouseHook <> 0
             End If
     End If
End Sub

Sub UnhookListBoxScroll()
     If mbHook Then
                Set mCtl = Nothing
             UnhookWindowsHookEx mLngMouseHook
             mLngMouseHook = 0
             mListBoxHwnd = 0
             mbHook = False
        End If
End Sub

Private Function MouseProc( _
             ByVal nCode As Long, ByVal wParam As Long, _
             ByRef lParam As MOUSEHOOKSTRUCT) As Long
Dim idx As Long
        On Error GoTo errH
     If (nCode = HC_ACTION) Then
             If WindowFromPoint(lParam.pt.X, lParam.pt.Y) = mListBoxHwnd Then
                     If wParam = WM_MOUSEWHEEL Then
                                MouseProc = True
'                                If lParam.hwnd > 0 Then
'                                        PostMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0
'                                Else
'                                        PostMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0
'                                End If
'                                PostMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0
                                If lParam.hwnd > 0 Then idx = -1 Else idx = 1
                             idx = idx + mCtl.ListIndex
                             If idx >= 0 Then mCtl.ListIndex = idx
                                Exit Function
                     End If
             Else
                     UnhookListBoxScroll
             End If
     End If
     MouseProc = CallNextHookEx( _
                             mLngMouseHook, nCode, wParam, ByVal lParam)
     Exit Function
errH:
     UnhookListBoxScroll
End Function
'''''''' end normal module code

'http://social.Msdn.microsoft.com/Forums/en-US/isvvba/thread/7d584120-a929-4e7c-9ec2-9998ac639bea#7738fb96-12be-4e3c-af5c-abaae64a5e94
'
'19-Jul-2012

''''' Userform code
Private Sub comboBox1_MouseMove( _
                        ByVal Button As Integer, ByVal Shift As Integer, _
                        ByVal X As Single, ByVal Y As Single)
                HookListBoxScroll Me, Me.ComboBox1
End Sub

Private Sub ListBox1_MouseMove( _
                        ByVal Button As Integer, ByVal Shift As Integer, _
                        ByVal X As Single, ByVal Y As Single)
         HookListBoxScroll Me, Me.ListBox1
End Sub

Private Sub ListBox2_MouseMove( _
                        ByVal Button As Integer, ByVal Shift As Integer, _
                        ByVal X As Single, ByVal Y As Single)
         HookListBoxScroll Me, Me.ListBox2
End Sub
Private Sub UserForm_Initialize()
Dim i As Long
Dim s As String
        s = "this is line "
        For i = 1 To 50
                        Me.ComboBox1.AddItem s & i
                        Me.ListBox1.AddItem s & i
                        Me.ListBox2.AddItem s & i
        Next
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
        UnhookListBoxScroll
End Sub
''''''' end Userform code
You can delete the commented PostMessage code
Peter Thornton
 
Last edited by a moderator:

Excel Facts

Format cells as date
Select range and press Ctrl+Shift+3 to format cells as date. (Shift 3 is the # sign which sort of looks like a small calendar).
Quite a few questions seem to crop up on variations of this code (which hooks the mouse to scroll controls on userforms).
I've never really explored the documentation on mouse hooks so, rather than addressing your specific question, I figured it would be a good learning exercise for me to create an example file to act as a reference point to cover all of these variations:


  • Scrolling userforms, comboboxes, listboxes, frames and multipage pages.
  • Works in both 32-bit and 64-bit Excel
  • Works for controls embedded inside other controls (eg comboboxes in a frame)
  • Works for controls created both at design time and at run time

The file can be downloaded from here.
If you have any questions about my example or if you spot any bugs/mistakes then please let me know.


This is also an opportune moment to mention that there are other ways to tackle this problem such as Jaafar's effort here.
 
Last edited:
Upvote 0
Hi Colin,

I haven't studied your code in detail but I liked the overall structure ...Good example of how to use abstract Intrefaces in VBA (IScrollable)

If you have any questions about my example or if you spot any bugs/mistakes then please let me know.

There seems to be a problem when applying the code to Modeless userforms .. the code crashes in the HookScroll Sub at the following line :
Code:
lngHwndControl = objScrollObject.GetHwnd
A quick debugging shows that the objScrollObject Object returns nothing which causes excel to crash.

Regards
 
Last edited:
Upvote 0
Hi Jaafar,

Thanks for reporting this. You're right: I managed to reproduce the error using modeless userforms in 64-bit Office. I couldn't reproduce it in 32-bit Office though: which version did you test the code in?

It's a bit of a weird one and I'm not yet sure why it's happening. I'll post back if my investigation gets anywhere.
 
Last edited:
Upvote 0
Hallo Colin,
thanks for the link to ScrollingControls.xlsb. I have the latest Windows 10 Home Edition 64bit and Excel 2010 32 bit edition. I opened your worksheet and dragged all of the appropriate modules to where they should be. It worked straight away with the listbox I have in a user form. It is a new project and I spent some time trying to get the Peter Thornton's version working I had in used in an earlier project, to no available. It works a treat :-)
 
Upvote 0
Hallo Colin
As I have said previously you routines work a treat. One annoying issue is that sometimes the mouse focus jumps to include the spreadsheet which it scrolls at the same time as the listbox. This happens after I have clicked on the listbox in a userform. The focus can be returned to just the userform listbox if a click the userform. Any ideas?
 
Upvote 0

Forum statistics

Threads
1,223,911
Messages
6,175,337
Members
452,636
Latest member
laura12345

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top