Option Explicit
Public Enum ToolTipPosEnum
topleft = 1
TopRight = 2
Bottomleft = 3
BottomRight = 4
FollowMousePointer = 5
End Enum
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] Win64 Then
Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "oleacc" (ByVal arg1 As LongPtr, ppacc As Any, pvarChild As Variant) As Long
Private Declare PtrSafe Function PtInRect Lib "user32" (lpRect As RECT, ByVal arg2 As LongPtr) As Long
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function SetClassLong Lib "user32" Alias "SetClassLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function GetClassLong Lib "user32" Alias "GetClassLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "oleacc" (ByVal lX As Long, ByVal lY As Long, ppacc As IAccessible, pvarChild As Variant) As Long
Private Declare PtrSafe Function PtInRect Lib "user32" (lpRect As RECT, ByVal X As Long, ByVal Y As Long) As Long
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As LongPtr
Private Declare PtrSafe Function SetClassLong Lib "user32" Alias "SetClassLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function GetClassLong Lib "user32" Alias "GetClassLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
Private Declare PtrSafe Function DrawMenuBar Lib "User32.dll" (ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function FrameRect Lib "user32" (ByVal hdc As LongPtr, lpRect As RECT, ByVal hBrush As LongPtr) As Long
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long
Private Declare PtrSafe Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As LongPtr
Private Declare PtrSafe Function DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As Long
Private Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function WindowFromAccessibleObject Lib "oleacc" (ByVal pacc As IAccessible, phwnd As LongPtr) As Long
Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Private Declare PtrSafe Function SetWindowPos Lib "user32" (ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetClassLong Lib "user32" Alias "SetClassLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetClassLong Lib "user32" Alias "GetClassLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function DrawMenuBar Lib "User32.dll" (ByVal hwnd As Long) As Long
Private Declare Function FrameRect Lib "user32" (ByVal hdc As Long, lpRect As RECT, ByVal hBrush As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function AccessibleObjectFromPoint Lib "oleacc" (ByVal lX As Long, ByVal lY As Long, ppacc As IAccessible, pvarChild As Variant) As Long
Private Declare Function PtInRect Lib "user32" (lpRect As RECT, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function WindowFromAccessibleObject Lib "oleacc" (ByVal pacc As IAccessible, phwnd 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 Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
Private Const GWL_STYLE = -16
Private Const GCL_STYLE = -26
Private Const WS_CAPTION = &HC00000
Private Const SWP_NOSIZE = &H1
Private Const CS_DROPSHADOW = &H20000
Private Const Xoffset = 5: Const Yoffset = 5: Const Mouseoffset = 20
Private tCursPos As POINTAPI, tControlRect As RECT
Private bFlag As Boolean, bClicked As Boolean
Public Function EnableMouseLeaveEevent _
( _
ByVal MainUserForm As Object, ByVal Ctrl As Object, ByVal ToolTipUserForm As Object, _
Optional ByVal TimeOutInSeconds As Long, Optional ByVal ToolTipFrameColor As Long, _
Optional ByVal ToolTipBackColor As Long, Optional ByVal ToolTipDropShadow As Boolean, _
Optional ByVal ToolTipPos As ToolTipPosEnum _
) As Boolean
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
Dim ToolTipHwnd As LongPtr, lStyle As LongPtr
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Dim ToolTipHwnd As Long, lStyle As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
Dim W As Long, h As Long
Dim oIA As IAccessible
If bFlag = False Then EnableMouseLeaveEevent = True
If bClicked = True Then EnableMouseLeaveEevent = False
GetCursorPos tCursPos
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
Dim Formhwnd As LongPtr
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] Win64 Then
Dim lngPtr As LongPtr
CopyMemory lngPtr, tCursPos, LenB(tCursPos)
Call AccessibleObjectFromPoint(lngPtr, oIA, 0)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Call AccessibleObjectFromPoint(tCursPos.X, tCursPos.Y, oIA, 0)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Dim Formhwnd As Long
Call AccessibleObjectFromPoint(tCursPos.X, tCursPos.Y, oIA, 0)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
WindowFromAccessibleObject MainUserForm, Formhwnd
WindowFromAccessibleObject ToolTipUserForm, ToolTipHwnd
With tControlRect
oIA.accLocation .Left, .Top, W, h, 0&
.Right = W + .Left
.Bottom = h + .Top
End With
lStyle = GetWindowLong(ToolTipHwnd, GWL_STYLE)
lStyle = lStyle And (Not WS_CAPTION)
SetWindowLong ToolTipHwnd, GWL_STYLE, lStyle
DrawMenuBar ToolTipHwnd
If ToolTipDropShadow Then
SetClassLong ToolTipHwnd, GCL_STYLE, GetClassLong(ToolTipHwnd, GCL_STYLE) Or CS_DROPSHADOW
End If
MainUserForm.Tag = UpdateTag(ObjPtr(ToolTipUserForm), ToolTipFrameColor, _
ToolTipDropShadow, TimeOutInSeconds, ToolTipPos)
SetTimer Formhwnd, CLng(ObjPtr(MainUserForm)), 0, AddressOf TimerProc
End Function
Public Sub MouseMoveMacro(Ctrl, ToolTipForm, TimeOut, FrameColor, BackColor, DropShadow, TollTipPos)
Static oControl As Object
Dim oLabel As Label, sPos As String
If Not oControl Is Ctrl Then
If ToolTipForm.Controls.Count = 0 Then
With ToolTipForm.Controls.Add("Forms.Label.1", "MyLabel")
.Width = ToolTipForm.Width
.Height = ToolTipForm.Height
.Left = 0
.Top = ToolTipForm.Height / 5
.TextAlign = 2
.BackStyle = 0
.Font.Bold = True
.Font.Size = 10
.Visible = True
End With
End If
ToolTipForm.Controls("MyLabel").Caption = "Hello from :" & vbCr & Ctrl.Name
Cells(1, 2) = ToolTipForm.Name
Cells(2, 2) = Ctrl.Name
Cells(3, 2) = IIf(TimeOut = 0, "None", TimeOut)
Cells(4, 2) = IIf(FrameColor = 0, "N/A", FrameColor)
Cells(5, 2) = IIf(BackColor = 0, "Default Color", BackColor)
Cells(6, 2) = DropShadow
Select Case TollTipPos
Case Is = topleft
sPos = "Topleft"
Case Is = TopRight
sPos = "TopRight"
Case Is = Bottomleft
sPos = "Bottomleft"
Case Is = BottomRight
sPos = "BottomRight"
Case Is = FollowMousePointer
sPos = "FollowMousePointer"
Case Else
sPos = "N/A"
End Select
Cells(7, 2) = sPos
End If
Set oControl = Ctrl
End Sub
Private Sub TimerProc(ByVal hwnd As Long, ByVal MSG As Long, ByVal nIDEvent As Long, ByVal dwTimer As Long)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
Dim hdc As LongPtr, hBrush As LongPtr, lToolTipHwnd As LongPtr
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Dim hdc As Long, hBrush As Long, lToolTipHwnd As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
Static tPrevCurPos As POINTAPI
Dim tToolTipFormRect As RECT
Dim tCurPos As POINTAPI
Dim sArray() As String
Dim oMainFormObj As Object, oTargetFormObj As Object, oIA As IAccessible
Dim lTimeOut As Long, lStartTimer As Long
Dim lTooltTipFrameColor As Long, lTooltTipDropShadow As Long
Dim l As Long, t As Long, lPos As Long
On Error Resume Next
CopyMemory oMainFormObj, nIDEvent, LenB(nIDEvent)
sArray = Split(oMainFormObj.Tag, "*")
CopyMemory oTargetFormObj, CLng(sArray(0)), LenB(nIDEvent)
If IsNumeric(sArray(1)) Then lTooltTipFrameColor = CLng(sArray(1))
If IsNumeric(sArray(2)) Then lTooltTipDropShadow = CLng(sArray(2))
If IsNumeric(sArray(3)) Then lTimeOut = CLng(sArray(3))
If IsNumeric(sArray(4)) Then lStartTimer = CLng(sArray(4))
If IsNumeric(sArray(5)) Then lPos = CLng(sArray(5))
GetCursorPos tCurPos
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] Win64 Then
Dim lPtr As LongPtr
CopyMemory lPtr, tCursPos, LenB(tCursPos)
Call AccessibleObjectFromPoint(lPtr, oIA, 0)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Call AccessibleObjectFromPoint(tCursPos.X, tCursPos.Y, oIA, 0)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Call AccessibleObjectFromPoint(tCursPos.X, tCursPos.Y, oIA, 0)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
Call GetAsyncKeyState(vbKeyLButton)
If GetAsyncKeyState(vbKeyLButton) Then
bClicked = True
oTargetFormObj.Hide
oIA.accDoDefaultAction 0&
oIA.accSelect 1, 0&
End If
If GetAsyncKeyState(vbKeyEscape) Then
bClicked = True
oTargetFormObj.Hide
End If
WindowFromAccessibleObject oTargetFormObj, lToolTipHwnd
If IsWindowVisible(lToolTipHwnd) Then
GetWindowRect lToolTipHwnd, tToolTipFormRect
With tToolTipFormRect
Select Case lPos
Case Is = topleft
l = tControlRect.Left - (.Right - .Left) - Xoffset
t = tControlRect.Top - (.Bottom - .Top) - Yoffset
Case Is = TopRight
l = tControlRect.Right + Xoffset
t = tControlRect.Top - (.Bottom - .Top) - Yoffset
Case Is = Bottomleft
l = tControlRect.Left - (.Right - .Left) - Xoffset
t = tControlRect.Bottom + Yoffset
Case Is = BottomRight
l = tControlRect.Right + Xoffset
t = tControlRect.Bottom + Yoffset
Case Is = FollowMousePointer
l = tCurPos.X + Mouseoffset
t = tCurPos.Y + Mouseoffset
Case Else
GoTo SetFrame
End Select
End With
SetWindowPos lToolTipHwnd, -1, l, t, 0, 0, SWP_NOSIZE
SetFrame:
If lTooltTipFrameColor Then
GetWindowRect lToolTipHwnd, tToolTipFormRect
hBrush = CreateSolidBrush(lTooltTipFrameColor)
hdc = GetDC(0)
FrameRect hdc, tToolTipFormRect, hBrush
ReleaseDC 0, hdc
DeleteObject hBrush
End If
End If
If lTooltTipDropShadow Then
Call SetClassLong(lToolTipHwnd, GCL_STYLE, CS_DROPSHADOW)
End If
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
Dim lngPtr As LongPtr
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] Win64 Then
CopyMemory lngPtr, tCurPos, LenB(tCurPos)
If PtInRect(tControlRect, lngPtr) = 0 Then
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
If PtInRect(tControlRect, tCurPos.X, tCurPos.Y) = 0 Then
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Dim lngPtr As Long
If PtInRect(tControlRect, tCurPos.X, tCurPos.Y) = 0 Then
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
bFlag = False
bClicked = False
KillTimer hwnd, nIDEvent
If lTooltTipDropShadow Then
SetClassLong lToolTipHwnd, GCL_STYLE, GetClassLong(lToolTipHwnd, GCL_STYLE) And Not CS_DROPSHADOW
End If
oTargetFormObj.Hide
'Debug.Print "Cursor moved outside control!"
Else
If lTimeOut > 0 Then
With tCurPos
If .X = tPrevCurPos.X And .Y = tPrevCurPos.Y Then
If Timer - lStartTimer > lTimeOut Then
bFlag = True
bClicked = False
lStartTimer = Timer
KillTimer hwnd, nIDEvent
If lTooltTipDropShadow Then
SetClassLong lToolTipHwnd, GCL_STYLE, _
GetClassLong(lToolTipHwnd, GCL_STYLE) And Not CS_DROPSHADOW
End If
oTargetFormObj.Hide
'Debug.Print "timeout!"
End If
Else
bFlag = False
oMainFormObj.Tag = _
UpdateTag(ObjPtr(oTargetFormObj), lTooltTipFrameColor, lTooltTipDropShadow, _
lTimeOut, lPos)
End If
End With
End If
End If
Xit:
CopyMemory oMainFormObj, 0, LenB(nIDEvent)
CopyMemory oTargetFormObj, 0, LenB(nIDEvent)
GetCursorPos tPrevCurPos
End Sub
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
Private Function UpdateTag(ByVal pFrmPointer As LongPtr, ByVal FrameColor As Long, _
ByVal shadow As Boolean, TimeOut As Long, ByVal TipPos As Long) As String
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Private Function UpdateTag(ByVal pFrmPointer As Long, ByVal FrameColor As Long, _
ByVal shadow As Boolean, TimeOut As Long, ByVal TipPos As Long) As String
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
UpdateTag = pFrmPointer & "*"
If FrameColor = 0 Then UpdateTag = UpdateTag & "-" & "*" Else UpdateTag = UpdateTag & FrameColor & "*"
If shadow = False Then UpdateTag = UpdateTag & "-" & "*" Else UpdateTag = UpdateTag & CLng(shadow) & "*"
If TimeOut < 1 Then UpdateTag = UpdateTag & "-" & "*" & "-" & "*" Else UpdateTag = UpdateTag & TimeOut & "*" & Timer & "*"
If TipPos = 0 Then UpdateTag = UpdateTag & "-" & "*" Else UpdateTag = UpdateTag & CLng(TipPos) & "*"
UpdateTag = UpdateTag
End Function