Option Explicit
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 GetCurrentThreadId Lib "kernel32" _
() As Long
Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount 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 SetWindowLong Lib "user32" _
Alias "SetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Private 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
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 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 Const WH_CBT As Long = 5
Private Const HCBT_CREATEWND As Long = 3
Private Const HCBT_DESTROYWND As Long = 4
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 lCBTHook As Long
Private lMouseHook As Long
Private lAppHwnd As Long
Private lDeskHwnd As Long
Private lWkbHwnd As Long
Private oValCell As Range
Private lDropDownHwnd As Long
Public Sub HookValidationList()
On Error Resume Next
Call RemoveHook
If HasValidateList(ActiveCell) Then
Set oValCell = ActiveCell
lAppHwnd = _
FindWindow("XLMAIN", Application.Caption)
lDeskHwnd = FindWindowEx _
(lAppHwnd, 0, "XLDESK", vbNullString)
lWkbHwnd = FindWindowEx _
(lDeskHwnd, 0, "EXCEL7", vbNullString)
lCBTHook = SetWindowsHookEx _
(WH_CBT, AddressOf CBTProc, _
GetAppInstance, GetCurrentThreadId)
SetProp Application.hwnd, "MouseHook", lMouseHook
SetProp Application.hwnd, "CBTHook", lCBTHook
Else
Call RemoveHook
End If
End Sub
Public Sub RemoveHook()
UnhookWindowsHookEx GetProp(Application.hwnd, "MouseHook")
UnhookWindowsHookEx GetProp(Application.hwnd, "CBTHook")
RemoveProp Application.hwnd, "MouseHook"
RemoveProp Application.hwnd, "CBTHook"
End Sub
Private Function CBTProc _
(ByVal idHook As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
Dim strBuffer As String
Dim lRetVal As Long
On Error Resume Next
Select Case idHook
Case Is = HCBT_CREATEWND
strBuffer = Space(256)
lRetVal = GetClassName(wParam, strBuffer, 256)
If Left(strBuffer, lRetVal) = "EXCEL:" Then
lDropDownHwnd = wParam
lMouseHook = SetWindowsHookEx _
(WH_MOUSE_LL, _
AddressOf LowLevelMouseProc, GetAppInstance, 0)
End If
Case Is = HCBT_DESTROYWND
If wParam = lDropDownHwnd Then
UnhookWindowsHookEx lMouseHook
UnhookWindowsHookEx lCBTHook
If ActiveCell.Address = oValCell.Address Then
Call HookValidationList
End If
End If
End Select
CBTProc = CallNextHookEx _
(lCBTHook, idHook, ByVal wParam, ByVal lParam)
End Function
Private Function LowLevelMouseProc _
(ByVal nCode As Long, ByVal wParam As Long, _
ByRef lParam As MSLLHOOKSTRUCT) As Long
On Error Resume Next
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
LowLevelMouseProc = _
CallNextHookEx(lMouseHook, 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