Option Explicit
Private Enum MouseAction
Click
DoubleClick
End Enum
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Type KeyboardBytes
kbByte(0 To 255) As Byte
End Type
#If VBA7 Then
#If Win64 Then
Private Declare PtrSafe Function GetTickCount Lib "kernel32" Alias "GetTickCount64" () As LongLong
#Else
Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
#End If
Private Declare PtrSafe Function GetDoubleClickTime Lib "user32" () As Long
Private Declare PtrSafe Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Declare PtrSafe Function GetKeyboardState Lib "user32" (kbArray As KeyboardBytes) As Long
Private Declare PtrSafe Function SetKeyboardState Lib "user32" (kbArray As KeyboardBytes) As Long
Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
#Else
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Function GetDoubleClickTime Lib "user32" () As Long
Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Declare Function GetKeyboardState Lib "user32" (kbArray As KeyboardBytes) As Long
Private Declare Function SetKeyboardState Lib "user32" (kbArray As KeyboardBytes) As Long
Private Declare Function GetActiveWindow Lib "user32" () As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
#End If
Private bDblClicked As Boolean
Private oPrev As Range
Private WithEvents CmBarsEvents As CommandBars
Private Const TARGET_SHEET_NAME = "Sheet1" '<== change target sheet name as needed.
Private Sub Workbook_Activate()
Call HookCommandBars
End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Sh.Name = TARGET_SHEET_NAME Then
Call HookCommandBars
End If
End Sub
Private Sub Workbook_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
If Sh.Name = TARGET_SHEET_NAME Then
Cancel = True
bDblClicked = True
If Not oPrev Is Nothing Then
If oPrev.Address = Target.Address Then
bDblClicked = False
End If
End If
Call MyMacro(Target, DoubleClick)
Call SetKeyState(vbKeyLButton)
End If
End Sub
Private Sub CmBarsEvents_OnUpdate()
Const FRACTION = 4 '<== change this const value if needed. (experiment with 1 to 6)
#If Win64 Then
Dim t As LongLong
#Else
Dim t As Long
#End If
Dim tCurPos As POINTAPI
If GetActiveWindow = Application.hwnd Then
If ActiveSheet.Name = TARGET_SHEET_NAME Then
Call GetCursorPos(tCurPos)
If TypeName(ActiveWindow.RangeFromPoint(tCurPos.X, tCurPos.Y)) = "Range" Then
t = GetTickCount
Do: DoEvents
Loop While GetTickCount - t <= GetDoubleClickTime / FRACTION
If bDblClicked = False Then
On Error Resume Next
If ActiveWindow.RangeSelection.Count = 1 Then
If Err.Number = 0 Then
On Error GoTo 0
If GetKeyState(vbKeyLButton) Then
Call MyMacro(ActiveCell, Click)
End If
End If
End If
Else
bDblClicked = False
End If
Call SetKeyState(vbKeyLButton)
bDblClicked = False
Set oPrev = ActiveCell
End If
End If
End If
End Sub
Private Sub HookCommandBars()
If CmBarsEvents Is Nothing Then
Set CmBarsEvents = Application.CommandBars
Call CmBarsEvents_OnUpdate
End If
End Sub
Private Sub SetKeyState(ByVal Key As Long)
Dim kbArray As KeyboardBytes
Call GetKeyState(Key)
Call GetKeyboardState(kbArray)
kbArray.kbByte(Key) = 0
Call SetKeyboardState(kbArray)
End Sub
Private Sub MyMacro(ByVal Target As Range, ByVal Action As MouseAction)
If Action = Click Then
Target = "Clicked"
Debug.Print "Cell Clicked: ", Target.Address
Else
Target = "Dbl-Clicked"
Debug.Print "Cell Double-Clicked: ", Target.Address
End If
End Sub