Hi, I recently found an excellent post by Jaafar Tribak on scrolling down ComboBox drop downs with the mouse wheel. I've tried running the following code.
This is the code attached to my ComboBox (CombBox9):
Option Explicit
Private Sub ComboBox9_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
Call SetComboBoxHook(ComboBox9)
End Sub
Private Sub ComboBox9_LostFocus()
Call RemoveComboBoxHook
End Sub
Private Sub ComboBox9_Change()
'change event not affected by the hook.
End Sub
-------------------------
And this is the code in my other module (Module2):
Option Explicit
Type POINTAPI
x As Long
y As Long
End Type
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Type MSLLHOOKSTRUCT
pt As POINTAPI
mouseData As Long
flags As Long
time As Long
dwExtraInfo As Long
End Type
#If VBA7 Then
#If Win64 Then
Declare PtrSafe Function WindowFromPoint Lib "user32" (ByVal Point As LongPtr) As LongPtr
#Else
Declare PtrSafe Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As LongPtr
#End If
Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare PtrSafe Function GetParent Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
Declare PtrSafe Function GetCursorPos Lib "user32" (ByRef lpPoint As POINTAPI) As LongPtr
Declare PtrSafe Function SetFocus Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function IsWindow Lib "user32" (ByVal hwnd As LongPtr) As Long
Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As LongPtr, ByVal hmod As LongPtr, ByVal dwThreadId As Long) As LongPtr
Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As LongPtr, ByVal nCode As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As LongPtr) As LongPtr
Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
Declare PtrSafe Function GetClientRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Declare PtrSafe Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As LongPtr)
Declare PtrSafe Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Dim hwnd As LongPtr, lMouseHook As LongPtr
#Else
Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetActiveWindow Lib "user32" () As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Declare Function GetCursorPos Lib "user32" (ByRef lpPoint As POINTAPI) As Long
Declare Function SetFocus Lib "user32" (ByVal hwnd As Long) As Long
Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
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
Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long)
Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Dim hwnd As Long, lMouseHook As Long
#End If
Const WH_MOUSE_LL = 14
Const WM_MOUSEWHEEL = &H20A
Const HC_ACTION = 0
Const WM_LBUTTONDOWN = &H201
Const WM_LBUTTONUP = &H202
Const MK_LBUTTON = &H1
Const SM_CXVSCROLL = 2
Dim oComboBox As Object
Sub SetComboBoxHook(ByVal Control As Object)
Dim tpt As POINTAPI
Dim sBuffer As String
Dim lRet As Long
Set oComboBox = Control
RemoveComboBoxHook
GetCursorPos tpt
#If VBA7 And Win64 Then
Dim lPt As LongPtr
CopyMemory lPt, tpt, LenB(tpt)
hwnd = WindowFromPoint(lPt)
#Else
hwnd = WindowFromPoint(tpt.x, tpt.y)
#End If
sBuffer = Space(256)
lRet = GetClassName(GetParent(hwnd), sBuffer, 256)
If InStr(Left(sBuffer, lRet), "MdcPopup") Then
SetFocus hwnd
#If VBA7 Then
lMouseHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf MouseProc, Application.HinstancePtr, 0)
#Else
lMouseHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf MouseProc, Application.Hinstance, 0)
#End If
End If
End Sub
Sub RemoveComboBoxHook()
UnhookWindowsHookEx lMouseHook
End Sub
#If VBA7 Then
Function MouseProc(ByVal nCode As Long, ByVal wParam As LongPtr, lParam As MSLLHOOKSTRUCT) As LongPtr
#Else
Function MouseProc(ByVal nCode As Long, ByVal wParam As Long, lParam As MSLLHOOKSTRUCT) As Long
#End If
Dim sBuffer As String
Dim lRet As Long
Dim tRect As RECT
sBuffer = Space(256)
lRet = GetClassName(GetActiveWindow, sBuffer, 256)
If Left(sBuffer, lRet) = "wndclass_desked_gsk" Then Call RemoveComboBoxHook
If IsWindow(hwnd) = 0 Then Call RemoveComboBoxHook
If (nCode = HC_ACTION) Then
If wParam = WM_MOUSEWHEEL Then
#If VBA7 And Win64 Then
Dim lPt As LongPtr
Dim Low As Long, High As Long
Dim lParm As LongPtr
CopyMemory lPt, lParam.pt, LenB(lPt)
If WindowFromPoint(lPt) = hwnd Then
#Else
Dim Low As Integer, High As Integer
Dim lParm As Long
If WindowFromPoint(lParam.pt.x, lParam.pt.y) = hwnd Then
#End If
GetClientRect hwnd, tRect
If lParam.mouseData > 0 Then
Low = tRect.Right - (GetSystemMetrics(SM_CXVSCROLL) / 2)
High = tRect.Top + ((GetSystemMetrics(SM_CXVSCROLL) / 2) + 1)
lParm = MakeLong_32_64(Low, High)
Else
Low = tRect.Right - (GetSystemMetrics(SM_CXVSCROLL) / 2)
High = tRect.Bottom - ((GetSystemMetrics(SM_CXVSCROLL) / 2) + 1)
lParm = MakeLong_32_64(Low, High)
End If
PostMessage hwnd, WM_LBUTTONDOWN, MK_LBUTTON, lParm
PostMessage hwnd, WM_LBUTTONUP, MK_LBUTTON, lParm
End If
End If
End If
MouseProc = CallNextHookEx(lMouseHook, nCode, wParam, ByVal lParam)
End Function
#If VBA7 And Win64 Then
Function MakeLong_32_64(ByVal wLow As Long, ByVal wHigh As Long) As LongPtr
Dim retVal As LongPtr, b(3) As Byte
MoveMemory ByVal VarPtr(b(0)), ByVal VarPtr(wLow), 4
MoveMemory ByVal VarPtr(b(2)), ByVal VarPtr(wHigh), 4
MoveMemory ByVal VarPtr(retVal), ByVal VarPtr(b(0)), 8
MakeLong_32_64 = retVal
#Else
Function MakeLong_32_64(ByVal wLow As Integer, ByVal wHigh As Integer) As Long
Dim retVal As Long, b(3) As Byte
MoveMemory ByVal VarPtr(b(0)), ByVal VarPtr(wLow), 2
MoveMemory ByVal VarPtr(b(2)), ByVal VarPtr(wHigh), 2
MoveMemory ByVal VarPtr(retVal), ByVal VarPtr(b(0)), 4
MakeLong_32_64 = retVal
#End If
End Function
-----------------------------------------
The code actually works for a few seconds, but then crashes. I get the following error:
Run-time error '91':
Object variable or With block variable not set.
When I run the Debugger, the following code is highlighed in my ComboBox9 code:
Private Sub ComboBox9_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
Call SetComboBoxHook(ComboBox9)
End Sub
I've tried to find the error, but no luck.
This is the code attached to my ComboBox (CombBox9):
Option Explicit
Private Sub ComboBox9_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
Call SetComboBoxHook(ComboBox9)
End Sub
Private Sub ComboBox9_LostFocus()
Call RemoveComboBoxHook
End Sub
Private Sub ComboBox9_Change()
'change event not affected by the hook.
End Sub
-------------------------
And this is the code in my other module (Module2):
Option Explicit
Type POINTAPI
x As Long
y As Long
End Type
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Type MSLLHOOKSTRUCT
pt As POINTAPI
mouseData As Long
flags As Long
time As Long
dwExtraInfo As Long
End Type
#If VBA7 Then
#If Win64 Then
Declare PtrSafe Function WindowFromPoint Lib "user32" (ByVal Point As LongPtr) As LongPtr
#Else
Declare PtrSafe Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As LongPtr
#End If
Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare PtrSafe Function GetParent Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
Declare PtrSafe Function GetCursorPos Lib "user32" (ByRef lpPoint As POINTAPI) As LongPtr
Declare PtrSafe Function SetFocus Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function IsWindow Lib "user32" (ByVal hwnd As LongPtr) As Long
Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As LongPtr, ByVal hmod As LongPtr, ByVal dwThreadId As Long) As LongPtr
Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As LongPtr, ByVal nCode As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As LongPtr) As LongPtr
Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
Declare PtrSafe Function GetClientRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Declare PtrSafe Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As LongPtr)
Declare PtrSafe Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Dim hwnd As LongPtr, lMouseHook As LongPtr
#Else
Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetActiveWindow Lib "user32" () As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Declare Function GetCursorPos Lib "user32" (ByRef lpPoint As POINTAPI) As Long
Declare Function SetFocus Lib "user32" (ByVal hwnd As Long) As Long
Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
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
Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long)
Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Dim hwnd As Long, lMouseHook As Long
#End If
Const WH_MOUSE_LL = 14
Const WM_MOUSEWHEEL = &H20A
Const HC_ACTION = 0
Const WM_LBUTTONDOWN = &H201
Const WM_LBUTTONUP = &H202
Const MK_LBUTTON = &H1
Const SM_CXVSCROLL = 2
Dim oComboBox As Object
Sub SetComboBoxHook(ByVal Control As Object)
Dim tpt As POINTAPI
Dim sBuffer As String
Dim lRet As Long
Set oComboBox = Control
RemoveComboBoxHook
GetCursorPos tpt
#If VBA7 And Win64 Then
Dim lPt As LongPtr
CopyMemory lPt, tpt, LenB(tpt)
hwnd = WindowFromPoint(lPt)
#Else
hwnd = WindowFromPoint(tpt.x, tpt.y)
#End If
sBuffer = Space(256)
lRet = GetClassName(GetParent(hwnd), sBuffer, 256)
If InStr(Left(sBuffer, lRet), "MdcPopup") Then
SetFocus hwnd
#If VBA7 Then
lMouseHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf MouseProc, Application.HinstancePtr, 0)
#Else
lMouseHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf MouseProc, Application.Hinstance, 0)
#End If
End If
End Sub
Sub RemoveComboBoxHook()
UnhookWindowsHookEx lMouseHook
End Sub
#If VBA7 Then
Function MouseProc(ByVal nCode As Long, ByVal wParam As LongPtr, lParam As MSLLHOOKSTRUCT) As LongPtr
#Else
Function MouseProc(ByVal nCode As Long, ByVal wParam As Long, lParam As MSLLHOOKSTRUCT) As Long
#End If
Dim sBuffer As String
Dim lRet As Long
Dim tRect As RECT
sBuffer = Space(256)
lRet = GetClassName(GetActiveWindow, sBuffer, 256)
If Left(sBuffer, lRet) = "wndclass_desked_gsk" Then Call RemoveComboBoxHook
If IsWindow(hwnd) = 0 Then Call RemoveComboBoxHook
If (nCode = HC_ACTION) Then
If wParam = WM_MOUSEWHEEL Then
#If VBA7 And Win64 Then
Dim lPt As LongPtr
Dim Low As Long, High As Long
Dim lParm As LongPtr
CopyMemory lPt, lParam.pt, LenB(lPt)
If WindowFromPoint(lPt) = hwnd Then
#Else
Dim Low As Integer, High As Integer
Dim lParm As Long
If WindowFromPoint(lParam.pt.x, lParam.pt.y) = hwnd Then
#End If
GetClientRect hwnd, tRect
If lParam.mouseData > 0 Then
Low = tRect.Right - (GetSystemMetrics(SM_CXVSCROLL) / 2)
High = tRect.Top + ((GetSystemMetrics(SM_CXVSCROLL) / 2) + 1)
lParm = MakeLong_32_64(Low, High)
Else
Low = tRect.Right - (GetSystemMetrics(SM_CXVSCROLL) / 2)
High = tRect.Bottom - ((GetSystemMetrics(SM_CXVSCROLL) / 2) + 1)
lParm = MakeLong_32_64(Low, High)
End If
PostMessage hwnd, WM_LBUTTONDOWN, MK_LBUTTON, lParm
PostMessage hwnd, WM_LBUTTONUP, MK_LBUTTON, lParm
End If
End If
End If
MouseProc = CallNextHookEx(lMouseHook, nCode, wParam, ByVal lParam)
End Function
#If VBA7 And Win64 Then
Function MakeLong_32_64(ByVal wLow As Long, ByVal wHigh As Long) As LongPtr
Dim retVal As LongPtr, b(3) As Byte
MoveMemory ByVal VarPtr(b(0)), ByVal VarPtr(wLow), 4
MoveMemory ByVal VarPtr(b(2)), ByVal VarPtr(wHigh), 4
MoveMemory ByVal VarPtr(retVal), ByVal VarPtr(b(0)), 8
MakeLong_32_64 = retVal
#Else
Function MakeLong_32_64(ByVal wLow As Integer, ByVal wHigh As Integer) As Long
Dim retVal As Long, b(3) As Byte
MoveMemory ByVal VarPtr(b(0)), ByVal VarPtr(wLow), 2
MoveMemory ByVal VarPtr(b(2)), ByVal VarPtr(wHigh), 2
MoveMemory ByVal VarPtr(retVal), ByVal VarPtr(b(0)), 4
MakeLong_32_64 = retVal
#End If
End Function
-----------------------------------------
The code actually works for a few seconds, but then crashes. I get the following error:
Run-time error '91':
Object variable or With block variable not set.
When I run the Debugger, the following code is highlighed in my ComboBox9 code:
Private Sub ComboBox9_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
Call SetComboBoxHook(ComboBox9)
End Sub
I've tried to find the error, but no luck.