Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
Option Explicit
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 SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex _
As Long, ByVal dwNewLong As Long) As Long
Private Const GWL_WNDPROC = -4
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONUP = &H202
Public Const WM_LBUTTONDBLCLK = &H203
Public Const WM_RBUTTONDOWN = &H204
Public Const WM_RBUTTONUP = &H205
Public Const WM_RBUTTONDBLCLK = &H206
Public Const WM_MBUTTONDOWN = &H207
Public Const WM_MBUTTONUP = &H208
Public Const WM_MBUTTONDBLCLK = &H209
Public Const WM_MOUSEWHEEL = &H20A
Public Const WM_MOUSEHOVER = &H2A1
Public Const WM_MOUSELEAVE = &H2A3
Public Const WM_CAPTURECHANGED = &H215
Public Const MK_LBUTTON = &H1
Public Const MK_RBUTTON = &H2
Public Const MK_SHIFT = &H4
Public Const MK_CONTROL = &H8
Public Const MK_MBUTTON = &H10
Private Type MouseHook
hwnd As Long 'Hwnd of the control
FriendlyName As String 'Name to be passed in ParentForms HandleMouse sub
ParentForm As Form 'The form the control belongs to
OldWindowProc As Long 'The old WindowProc pointer
End Type
Private MouseHooks() As MouseHook 'Where we keep all the hooks
Public Sub HookMouse(hwnd As Long, FriendlyName As String, ParentForm As Form)
'Add An Item To the Array
Dim A As Long
'In-line Error Handling
On Error Resume Next
A = UBound(MouseHooks()) 'Generates Error If Not Initialised
If Err.Number <> 0 Then 'If Error Occurred
Err.Clear 'Clear It
On Error GoTo 0 'Reinstate Default Error Handling
ReDim MouseHooks(0) 'Initialise The Array
Else
On Error GoTo 0 'Reinstate Default Error Handling
If MouseHooks(0).hwnd <> 0 Then 'If hWnd Of First Item Not Zero (Unused)
ReDim Preserve MouseHooks(UBound(MouseHooks()) + 1) 'Add An Item
End If
End If
'And Hook The WindowProc
With MouseHooks(UBound(MouseHooks()))
.hwnd = hwnd
.FriendlyName = FriendlyName
Set .ParentForm = ParentForm
.OldWindowProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf MouseHookWindowProc)
'Debug.Print FriendlyName & " Hooked As Item " & UBound(MouseHooks())
End With
End Sub
Public Sub UnhookMouse(hwnd As Long)
Dim Temp As Long
Dim A As Long
Dim FriendlyName As String
'As We Can't Reset The Array To No Items, Set The hWnd Of Item 0 To 0 When Empty
If MouseHooks(0).hwnd <> 0 Then
For A = 0 To UBound(MouseHooks())
If MouseHooks(A).hwnd = hwnd Then
With MouseHooks(A)
'Unhook WindowProc
Temp = SetWindowLong(.hwnd, GWL_WNDPROC, .OldWindowProc)
FriendlyName = .FriendlyName
End With
Temp = A
Exit For
End If
Next A
'Debug.Print FriendlyName & " Unhooked As Item " & Temp
'If Not Last One In Array (We Can't Un-Dim An Array !)
If UBound(MouseHooks()) > 0 Then
'Shuffle Down To Fill Gap
For A = Temp To UBound(MouseHooks()) - 1
MouseHooks(A) = MouseHooks(A + 1)
Next A
'And Remove Last Item
ReDim Preserve MouseHooks(UBound(MouseHooks()) - 1)
Else
MouseHooks(0).hwnd = 0
End If
End If
End Sub
Function MouseHookWindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim Temp As Long
Dim A As Long
'Find the Item
On Error Resume Next
If MouseHooks(0).hwnd <> 0 Then
For A = 0 To UBound(MouseHooks())
If MouseHooks(A).hwnd = hw Then
With MouseHooks(A)
Select Case uMsg
'WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP,
Case WM_RBUTTONDOWN, WM_RBUTTONUP, WM_RBUTTONDBLCLK:
'Get The Parent Form To Do Its Thing
.ParentForm.HandleMouseHook .FriendlyName, uMsg, wParam, lParam
'Return Zero (As We Should For Mouse Up/Down Messages)
MouseHookWindowProc = 0
Case Else
'Call the original handler for any non-handled messages
MouseHookWindowProc = CallWindowProc(.OldWindowProc, hw, uMsg, wParam, lParam)
End Select
End With
Exit For
End If
Next A
End If
End Function
SetWindowLong hwnd, GWL_WNDPROC, OriginalWindowProc