Option Explicit
#If VBA7 Then
#If Win64 Then
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
#Else
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As LongPtr
#End If
Private 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
Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hhk As LongPtr) As Long
Private Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As LongPtr, ByVal nCode As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Private Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long
Private Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As LongPtr, ByVal hWnd As LongPtr, ByVal MSG As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
Private Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare PtrSafe Function SetProp Lib "user32" Alias "SetPropA" (ByVal hWnd As LongPtr, ByVal lpString As String, ByVal hData As LongPtr) As Long
Private Declare PtrSafe Function GetProp Lib "user32" Alias "GetPropA" (ByVal hWnd As LongPtr, ByVal lpString As String) As LongPtr
Private Declare PtrSafe Function GetDlgItem Lib "user32" (ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long) As LongPtr
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
#Else
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 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 UnhookWindowsHookEx Lib "user32" (ByVal hhk 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 GetCurrentThreadId Lib "kernel32" () 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 GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount 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 GetProp Lib "user32" Alias "GetPropA" (ByVal hwnd As Long, ByVal lpString As String) As Long
Private Declare Function GetDlgItem Lib "user32" (ByVal hDlg As Long, ByVal nIDDlgItem As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetActiveWindow Lib "user32" () As Long
#End If
Public Property Let CustomizeDataValidationHelpButton(ByVal Cell As Range, ByVal Customize As Boolean)
Const WH_CBT = 5
#If VBA7 Then
Dim lHook As LongPtr
#Else
Dim lHook As Long
#End If
If Customize Then
UnhookWindowsHookEx GetProp(Application.hWnd, "Hook")
lHook = SetWindowsHookEx(WH_CBT, AddressOf HookProc, 0, GetCurrentThreadId)
SetProp Application.hWnd, "Hook", lHook
Else
UnhookWindowsHookEx GetProp(Application.hWnd, "Hook")
End If
End Property
#If VBA7 Then
Private Function HookProc(ByVal idHook As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
#Else
Private Function HookProc(ByVal idHook As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#End If
Const HCBT_ACTIVATE = 5
Dim sBuff As String * 256, lRet As Long
If IsVBEActive Then
UnhookWindowsHookEx GetProp(Application.hWnd, "Hook")
Exit Function
End If
If idHook = HCBT_ACTIVATE Then
lRet = GetClassName(wParam, sBuff, 256)
If Left(sBuff, lRet) = "#32770" Then
If GetDlgItem(wParam, &HFA1) Then
UnhookWindowsHookEx GetProp(Application.hWnd, "Hook")
Call SubClassPrompt(wParam, True)
End If
End If
End If
HookProc = CallNextHookEx(GetProp(Application.hWnd, "Hook"), idHook, ByVal wParam, ByVal lParam)
End Function
#If VBA7 Then
Private Sub SubClassPrompt(ByVal hWnd As LongPtr, ByVal Subclass As Boolean)
#Else
Private Sub SubClassPrompt(ByVal hWnd As Long, ByVal Subclass As Boolean)
#End If
Const GWL_WNDPROC = -4
#If VBA7 Then
Dim lPrevProc As LongPtr
#Else
Dim lPrevProc As Long
#End If
If Subclass Then
lPrevProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
SetProp Application.hWnd, "PrevProc", lPrevProc
Else
Call SetWindowLong(hWnd, GWL_WNDPROC, GetProp(Application.hWnd, "PrevProc"))
End If
End Sub
#If VBA7 Then
Private Function WindowProc(ByVal hWnd As LongPtr, ByVal MSG As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
#Else
Private Function WindowProc(ByVal hWnd As Long, ByVal MSG As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#End If
Const WM_COMMAND = &H111
Const WM_DESTROY = &H2
Select Case MSG
Case WM_COMMAND
#If Win64 Then
Static Low As LongPtr
Static High As LongPtr
#Else
Static Low As Long
Static High As Long
#End If
GetHiLoword wParam, Low, High
If Low = &H9 Then
CustomHelpUserForm.Show
Exit Function
End If
Case WM_DESTROY
If Low = &H7 Then
CustomizeDataValidationHelpButton(ActiveCell) = True
Else
UnhookWindowsHookEx GetProp(Application.hWnd, "Hook")
End If
Call SubClassPrompt(hWnd, False)
End Select
WindowProc = CallWindowProc(GetProp(Application.hWnd, "PrevProc"), hWnd, MSG, wParam, ByVal lParam)
End Function
#If Win64 Then
Private Sub GetHiLoword(lParam As LongPtr, ByRef loword As LongPtr, ByRef hiword As LongPtr)
#Else
Private Sub GetHiLoword(lParam As Long, ByRef loword As Long, ByRef hiword As Long)
#End If
loword = lParam And &HFFFF&
hiword = lParam \ &H10000 And &HFFFF&
End Sub
Private Function IsVBEActive() As Boolean
IsVBEActive = CBool(GetActiveWindow = FindWindow("wndclass_desked_gsk", vbNullString))
End Function
Private Sub Auto_Close()
UnhookWindowsHookEx GetProp(Application.hWnd, "Hook")
End Sub