Option Explicit
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type MSLLHOOKSTRUCT
pt As POINTAPI
mouseData As Long
flags As Long
time 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 FindWindowEx Lib "user32" _
Alias "FindWindowExA" _
(ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
Private Declare Function IsWindow Lib "user32" _
(ByVal hwnd As Long) As Long
Private Declare Function GetWindowLong Lib "user32" _
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 SetTimer Lib "user32" _
(ByVal hwnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" _
(ByVal hwnd As Long, _
ByVal nIDEvent As Long) As Long
Private Declare Function WindowFromPoint Lib "user32" _
(ByVal xPoint As Long, _
ByVal yPoint As Long) As Long
Private Declare Function ShowWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long
Private Declare Function SetProp Lib "user32" Alias "SetPropA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal hData As Long) As Long
Private Declare Function RemoveProp Lib "user32" Alias "RemovePropA" _
(ByVal hwnd As Long, _
ByVal lpString As String) As Long
Private Declare Function GetProp Lib "user32" Alias "GetPropA" _
(ByVal hwnd As Long, _
ByVal lpString As String) 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 lMouseHook As Long
Private lAppHwnd As Long
Private lDeskHwnd As Long
Private lWkbHwnd As Long
Private lDropDownHwnd As Long
Public Sub HookValidationList(Cell As Range)
Call RemoveHook
If HasValidateList(Cell) Then
lAppHwnd = _
FindWindow("XLMAIN", Application.Caption)
lDeskHwnd = FindWindowEx _
(lAppHwnd, 0, "XLDESK", vbNullString)
lWkbHwnd = FindWindowEx _
(lDeskHwnd, 0, "EXCEL7", vbNullString)
SetTimer Application.hwnd, 0, 100, AddressOf TimerProc
Else
Call RemoveHook
End If
End Sub
Public Sub RemoveHook()
KillTimer Application.hwnd, 0
UnhookWindowsHookEx GetProp(Application.hwnd, "MouseHook")
RemoveProp Application.hwnd, "MouseHook"
End Sub
Private Sub TimerProc()
lDropDownHwnd = FindWindow("EXCEL:", vbNullString)
If lDropDownHwnd <> 0 Then
Call RemoveHook
lMouseHook = SetWindowsHookEx _
(WH_MOUSE_LL, AddressOf LowLevelMouseProc, GetAppInstance, 0)
SetProp Application.hwnd, "MouseHook", lMouseHook
End If
End Sub
Private Function LowLevelMouseProc _
(ByVal nCode As Long, ByVal wParam As Long, _
ByRef lParam As MSLLHOOKSTRUCT) As Long
If (nCode = HC_ACTION) Then
If wParam = WM_MOUSEWHEEL Then
LowLevelMouseProc = True
If lParam.mouseData > 0 Then
SendKeys "{UP}"
Else
SendKeys "{DOWN}"
End If
Exit Function
End If
With lParam.pt
If WindowFromPoint(.x, .y) <> lDropDownHwnd _
And WindowFromPoint(.x, .y) <> lWkbHwnd Then
ShowWindow lDropDownHwnd, 0
End If
End With
End If
If IsWindow(lDropDownHwnd) Then Call HookValidationList(ActiveCell)
LowLevelMouseProc = _
CallNextHookEx(GetProp(Application.hwnd, "MouseHook"), nCode, wParam, ByVal lParam)
End Function
Private Function GetAppInstance() As Long
GetAppInstance = GetWindowLong(lAppHwnd, GWL_HINSTANCE)
End Function
Private Function HasValidateList(Cell As Range) As Boolean
On Error Resume Next
HasValidateList = Cell.Validation.InCellDropdown
End Function