Generic Class for detecting Mouse Enter & Leave Events on Userform Controls.

Jaafar Tribak

Well-known Member
Joined
Dec 5, 2002
Messages
9,621
Office Version
  1. 2016
Platform
  1. Windows
The code doesn't rely entirely on the native MouseMove event. This so that it detects when the mouse leaves controls that overlap or those that are located at the edges of the userform... It also works on controls that are located inside Frames and Multipages... The Class as well as the pseudo-events are very easy to use by the userform.

Workbook Demo









1- Class Code (C_MouseEnterLeave)
VBA Code:
Option Explicit

Private Type POINTAPI
        x As Long
        Y As Long
End Type

#If VBA7 Then
    #If Win64 Then
        Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "oleacc" (ByVal arg1 As LongLong, ppacc As Any, pvarChild As Variant) As Long
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongLong)
    #Else
        Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "oleacc" (ByVal lX As Long, ByVal lY As Long, ppacc As IAccessible, pvarChild As Variant) As Long
    #End If
    Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
#Else
    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 GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
#End If

Private WithEvents lbl As MsForms.Label
Private WithEvents txt As MsForms.TextBox
Private WithEvents cbx As MsForms.ComboBox
Private WithEvents lbx As MsForms.ListBox
Private WithEvents chx As MsForms.CheckBox
Private WithEvents opt As MsForms.OptionButton
Private WithEvents tgl As MsForms.ToggleButton
Private WithEvents frm As MsForms.Frame
Private WithEvents cbt As MsForms.CommandButton
Private WithEvents tbs As MsForms.TabStrip
Private WithEvents mlp As MsForms.MultiPage
Private WithEvents img As MsForms.Image

Private oThis  As C_MouseEnterLeave, oForm As Object




'________________________________Class Public Method__________________________________________________

Public Sub AddControl(ByVal ThisClass As C_MouseEnterLeave, ByVal Ctrl As MsForms.Control)

    Set oThis = ThisClass
    Set oForm = GetUserFormObject(Ctrl)
  
    Select Case True
        Case TypeOf Ctrl Is MsForms.Label
            Set lbl = Ctrl
        Case TypeOf Ctrl Is MsForms.TextBox
            Set txt = Ctrl
        Case TypeOf Ctrl Is MsForms.ComboBox
            Set cbx = Ctrl
        Case TypeOf Ctrl Is MsForms.ListBox
            Set lbx = Ctrl
        Case TypeOf Ctrl Is MsForms.CheckBox
            Set chx = Ctrl
        Case TypeOf Ctrl Is MsForms.OptionButton
            Set opt = Ctrl
        Case TypeOf Ctrl Is MsForms.ToggleButton
            Set tgl = Ctrl
        Case TypeOf Ctrl Is MsForms.Frame
            Set frm = Ctrl
        Case TypeOf Ctrl Is MsForms.CommandButton
            Set cbt = Ctrl
        Case TypeOf Ctrl Is MsForms.TabStrip
            Set tbs = Ctrl
        Case TypeOf Ctrl Is MsForms.MultiPage
            Set mlp = Ctrl
        Case TypeOf Ctrl Is MsForms.Image
            Set img = Ctrl
    End Select

End Sub



'________________________________Class Private Routines__________________________________________________

Private Sub GenericMouseMoveEvent(ByVal Ctrl As MsForms.Control, Optional ByVal Index As Long)

    Const CHILDID_SELF = &H0&
    Const ROLE_SYSTEM_PANE = &H10
  
    Static bDoLooping As Boolean
  
    Dim tCurPos As POINTAPI, oCurAcc As IAccessible, oPrevAcc As IAccessible
    Dim px1 As Long, py1 As Long, pw1 As Long, ph1 As Long
    Dim px2 As Long, py2 As Long, pw2 As Long, ph2 As Long
    Dim sCurAccLocation As String, sPrevAccLocation As String


    If bDoLooping Or oForm.Tag = "TaggedUserForm" Then Exit Sub
    oForm.Tag = "TaggedUserForm"
  
    Do
  
        bDoLooping = True
        Call GetCursorPos(tCurPos)
      
        #If Win64 Then
            Dim ptr As LongLong
            Call CopyMemory(ptr, tCurPos, LenB(tCurPos))
            Call AccessibleObjectFromPoint(ptr, oCurAcc, 0&)
        #Else
            Call AccessibleObjectFromPoint(tCurPos.x, tCurPos.Y, oCurAcc, 0&)
        #End If
      
        Call oCurAcc.accLocation(px1, py1, pw1, ph1, CHILDID_SELF)
        If Not oPrevAcc Is Nothing Then
            Call oPrevAcc.accLocation(px2, py2, pw2, ph2, CHILDID_SELF)
        End If
        sCurAccLocation = CStr(px1) & CStr(py1) & CStr(pw1) & CStr(ph1)
        sPrevAccLocation = CStr(px2) & CStr(py2) & CStr(pw2) & CStr(ph2)
      
        If oPrevAcc Is Nothing And sCurAccLocation <> sPrevAccLocation Then
            Call oForm.UserForm_OnControlMouseEnter(Ctrl)
        End If
        Set oPrevAcc = Ctrl
        Call oPrevAcc.accLocation(px2, py2, pw2, ph2, CHILDID_SELF)
      
        If TypeOf Ctrl Is MsForms.MultiPage And oCurAcc.accRole(0&) = ROLE_SYSTEM_PANE Then
            Set oPrevAcc = Ctrl.Pages(Ctrl.Value)
            Call oPrevAcc.accLocation(px2, py2, pw2, ph2, CHILDID_SELF)
        End If
      
        sPrevAccLocation = CStr(px2) & CStr(py2) & CStr(pw2) & CStr(ph2)
      
        DoEvents
      
    Loop Until sCurAccLocation <> sPrevAccLocation
  
    bDoLooping = False
    Call oForm.UserForm_OnControlMouseLeave(Ctrl)
    oForm.Tag = ""

End Sub

Private Function GetUserFormObject(ByVal Ctrl As MsForms.Control) As Object

    Dim oTemp As Object
  
    Set oTemp = Ctrl.Parent
    Do While TypeOf oTemp Is MsForms.Control
        Set oTemp = oTemp.Parent
        DoEvents
    Loop
    Set GetUserFormObject = oTemp
  
End Function

Private Sub lbl_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(lbl)
End Sub
Private Sub txt_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(txt)
End Sub
Private Sub cbx_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(cbx)
End Sub
Private Sub lbx_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(lbx)
End Sub
Private Sub chx_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(chx)
End Sub
Private Sub opt_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(opt)
End Sub
Private Sub tgl_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(tgl)
End Sub
Private Sub frm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(frm)
End Sub
Private Sub cbt_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(cbt)
End Sub
Private Sub tbs_MouseMove(ByVal Index As Long, ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(tbs)
End Sub
Private Sub mlp_MouseMove(ByVal Index As Long, ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(mlp, Index + 1)
End Sub
Private Sub img_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    Call GenericMouseMoveEvent(img)
End Sub




2- Code Usage (UserForm)
VBA Code:
Option Explicit

'Jaafar Tribak @MrExcel.com on 07/09/2020
'Class Name : C_MouseEnterLeave:
'Class Only Method : AddControl(ByVal ThisClass As C_MouseEnterLeave, ByVal Ctrl As MsForms.Control)


Private Sub UserForm_Initialize()

    Dim oClass As C_MouseEnterLeave
    Dim oCtrl As MsForms.Control
  
    For Each oCtrl In Me.Controls
        Set oClass = New C_MouseEnterLeave
        Call oClass.AddControl(ThisClass:=oClass, Ctrl:=oCtrl)
    Next

End Sub


'Pseudo-Events Handlers Must Be Declared As PUBLIC !!
'=============================================

Public Sub UserForm_OnControlMouseEnter(ByVal Ctrl As MsForms.Control)
  
    If TypeOf Ctrl Is MultiPage Then
        Debug.Print "Mouse Entered ...  (" & Ctrl.Name & ")" & Ctrl.Pages(Ctrl.Value).Name
    Else
        Debug.Print "Mouse Entered ...  (" & Ctrl.Name & ")"
    End If
  
End Sub


Public Sub UserForm_OnControlMouseLeave(ByVal Ctrl As MsForms.Control)

    If TypeOf Ctrl Is MultiPage Then
        Debug.Print "Mouse Left ...  (" & Ctrl.Name & ")" & Ctrl.Pages(Ctrl.Value).Name
    Else
        Debug.Print "Mouse Left ...  (" & Ctrl.Name & ")"
    End If

End Sub
 

Excel Facts

Copy formula down without changing references
If you have =SUM(F2:F49) in F50; type Alt+' in F51 to copy =SUM(F2:F49) to F51, leaving the formula in edit mode. Change SUM to COUNT.
Ok - Below is the new version. The code now sinks the controls mousemove event at runtime so the above-mentioned error no longer occurs.

Unlike the previous code, this new code is designed more in line with the object oriented model (Event-RaiseEvent-WithEvents-Implements), therefore it is more intuitive and easier to use from the user perspective.

MouseEnterLeave_V2.xlsm






1- C_MouseEnterLeave Class:
VBA Code:
Option Explicit

Implements I_Hidden
Event OnControlMouseEnter(ByVal Ctrl As MSForms.Control, ByVal Page As MSForms.Page)
Event OnControlMouseLeave(ByVal Ctrl As MSForms.Control, ByVal Page As MSForms.Page)
Private WithEvents oTabStrip As MSForms.TabStrip
Private WithEvents oMutliPage As MSForms.MultiPage

Private Type POINTAPI
    X As Long
    Y As Long
End Type

Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(0 To 7) As Byte
End Type

#If VBA7 Then
    #If Win64 Then
        Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "oleacc" (ByVal arg1 As LongLong, ppacc As Any, pvarChild As Variant) As Long
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongLong)
    #Else
        Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "oleacc" (ByVal lX As Long, ByVal lY As Long, ppacc As IAccessible, pvarChild As Variant) As Long
    #End If
    Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Declare PtrSafe Function IIDFromString Lib "ole32.dll" (ByVal lpsz As LongPtr, lpiid As GUID) As Long
    Private Declare PtrSafe Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As stdole.IUnknown, ByRef riidEvent As GUID, ByVal fConnect As Long, ByVal punkTarget As stdole.IUnknown, ByRef pdwCookie As Long, Optional ByVal ppcpOut As LongPtr) As Long
    Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
    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 hForm As LongPtr
#Else
    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 GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Declare Function IIDFromString Lib "ole32.dll" (ByVal lpsz As Long, lpiid As GUID) As Long
    Private Declare Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As stdole.IUnknown, ByRef riidEvent As GUID, ByVal fConnect As Long, ByVal punkTarget As stdole.IUnknown, ByRef pdwCookie As Long, Optional ByVal ppcpOut As Long) As Long
    Private Declare Function GetActiveWindow Lib "user32" () 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 hForm As Long
#End If

Private oForm As Object, oCtrl As MSForms.Control


'___________________________________________ Class Init __________________________________________________

Private Sub Class_Initialize()
    hForm = GetActiveWindow
End Sub


'__________________________________________ Class Public Method __________________________________________________


Public Sub HookControls(ByVal Frm As MSForms.UserForm, ByVal bHook As Boolean)
    Dim oClass As I_Hidden
    Dim oCtrl As MSForms.Control
    If bHook Then
        Call SetProp(hForm, "HOOKED", -1)
        For Each oCtrl In Frm.Controls
            Set oClass = New C_MouseEnterLeave
            Call oClass.SetControlEvent(oCtrl)
        Next
    Else
        Call SetProp(hForm, "HOOKED", 0)
    End If
End Sub


'__________________________________________ Interface Implementation __________________________________________________

Private Sub I_Hidden_SetControlEvent(ByVal Ctrl As MSForms.Control)
    Set oCtrl = Ctrl
    Set oForm = GetUserFormObject(Ctrl)
    SetControlEvents(Me, Ctrl) = True
    Select Case True
        Case TypeOf Ctrl Is MSForms.TabStrip
            Set oTabStrip = Ctrl
        Case TypeOf Ctrl Is MSForms.MultiPage
            Set oMutliPage = Ctrl
    End Select
End Sub


'__________________________________________ Class Private Routines__________________________________________________

Private Sub GenericMouseMoveEvent(ByVal Ctrl As MSForms.Control, Optional ByVal Index As Long)

    Const CHILDID_SELF = &H0&
    Const ROLE_SYSTEM_PANE = &H10
    
    Static bDoLooping As Boolean
    
    Dim tCurPos As POINTAPI, oCurAcc As IAccessible, oPrevAcc As IAccessible
    Dim px1 As Long, py1 As Long, pw1 As Long, ph1 As Long
    Dim px2 As Long, py2 As Long, pw2 As Long, ph2 As Long
    Dim sCurAccLocation As String, sPrevAccLocation As String
    Dim oPage As MSForms.Page
    
    If bDoLooping Or oForm.Tag = "TaggedUserForm" Then Exit Sub
    oForm.Tag = "TaggedUserForm"

    Do
        bDoLooping = True
        Set oForm.Form = Me
        Call GetCursorPos(tCurPos)
        
        #If Win64 Then
            Dim ptr As LongLong
            Call CopyMemory(ptr, tCurPos, LenB(tCurPos))
            Call AccessibleObjectFromPoint(ptr, oCurAcc, CHILDID_SELF)
        #Else
            Call AccessibleObjectFromPoint(tCurPos.X, tCurPos.Y, oCurAcc, CHILDID_SELF)
        #End If
        
        Call oCurAcc.accLocation(px1, py1, pw1, ph1, CHILDID_SELF)
        If Not oPrevAcc Is Nothing Then
            Call oPrevAcc.accLocation(px2, py2, pw2, ph2, CHILDID_SELF)
        End If
        sCurAccLocation = CStr(px1) & CStr(py1) & CStr(pw1) & CStr(ph1)
        sPrevAccLocation = CStr(px2) & CStr(py2) & CStr(pw2) & CStr(ph2)
        
        If TypeOf Ctrl Is MSForms.MultiPage Then
            Set oPage = Ctrl.Pages(Ctrl.Value)
        Else
            Set oPage = Nothing
        End If

        If Not oPrevAcc Is Nothing And sCurAccLocation <> sPrevAccLocation Then
            RaiseEvent OnControlMouseLeave(Ctrl, oPage)
        End If
        
        If oPrevAcc Is Nothing And sCurAccLocation <> sPrevAccLocation Then
            RaiseEvent OnControlMouseEnter(Ctrl, oPage)
        End If

        Set oPrevAcc = Ctrl
        Call oPrevAcc.accLocation(px2, py2, pw2, ph2, CHILDID_SELF)
        
        If TypeOf Ctrl Is MSForms.MultiPage And oCurAcc.accRole(0&) = ROLE_SYSTEM_PANE Then
            Set oPrevAcc = Ctrl.Pages(Ctrl.Value)
            Call oPrevAcc.accLocation(px2, py2, pw2, ph2, CHILDID_SELF)
        End If
        
        sPrevAccLocation = CStr(px2) & CStr(py2) & CStr(pw2) & CStr(ph2)
        
        DoEvents
        
    Loop Until sCurAccLocation <> sPrevAccLocation

    bDoLooping = False
    oForm.Tag = ""

End Sub

Private Function GetUserFormObject(ByVal Ctrl As MSForms.Control) As Object
    Dim oTemp As Object
    Set oTemp = Ctrl.Parent
    Do While TypeOf oTemp Is MSForms.Control
        Set oTemp = oTemp.Parent
        DoEvents
    Loop
    Set GetUserFormObject = oTemp
End Function

Private Property Let SetControlEvents(oSinkClass As Object, ByVal Ctrl As Object, ByVal SetEvents As Boolean)
    Const S_OK = &H0
    Const IDISPATCH = "{00020400-0000-0000-C000-000000000046}"
    Static lCookie As Long
    Dim tIID As GUID
    
    If IIDFromString(StrPtr(IDISPATCH), tIID) = S_OK Then
        Call ConnectToConnectionPoint(oSinkClass, tIID, SetEvents, Ctrl, lCookie)
        If lCookie Then
            'Debug.Print "Connection set for: " & Ctrl.Name
        Else
            'Debug.Print "Connection failed for: " & Ctrl.Name
        End If
    End If
End Property


'______________________________________________ EVENTS ________________________________________________________

Private Sub oTabStrip_MouseMove( _
    ByVal Index As Long, _
    ByVal Button As Integer, _
    ByVal Shift As Integer, _
    ByVal X As Single, _
    ByVal Y As Single _
)
    If GetProp(hForm, "HOOKED") Then
        Call GenericMouseMoveEvent(oTabStrip, oTabStrip.Value)
    End If
End Sub

Private Sub oMutliPage_MouseMove( _
    ByVal Index As Long, _
    ByVal Button As Integer, _
    ByVal Shift As Integer, _
    ByVal X As Single, _
    ByVal Y As Single _
)

    If GetProp(hForm, "HOOKED") Then
        Call GenericMouseMoveEvent(oMutliPage, Index)
    End If
End Sub

Public Sub OnMouseMove_DoNotUse( _
    ByVal Button As Integer, _
    ByVal Shift As Integer, _
    ByVal X As Single, _
    ByVal Y As Single _
)
    'Attribute OnMouseMove_DoNotUse.VB_UserMemId = -606
    If GetProp(hForm, "HOOKED") Then
        Call GenericMouseMoveEvent(oCtrl)
    End If
End Sub


2- I_Hidden Interface:
VBA Code:
Option Explicit

Public Sub SetControlEvent(ByVal Ctrl As MSForms.Control)
'
End Sub


3- UserForm Usage Example:
VBA Code:
Option Explicit

Public WithEvents Form As C_MouseEnterLeave

Private Sub UserForm_Initialize()
    Set Form = New C_MouseEnterLeave
    Form.HookControls Me, True
    btnEnableEvent.Enabled = False
End Sub

Private Sub btnDisableEvent_Click()
    Form.HookControls Me, False
    btnEnableEvent.Enabled = True
    btnDisableEvent.Enabled = False
End Sub

Private Sub btnEnableEvent_Click()
    Form.HookControls Me, True
    btnEnableEvent.Enabled = False
    btnDisableEvent.Enabled = True
End Sub


'____________________________________ MOUSE ENTER\LEAVE EVENETS _________________________________________________

Private Sub Form_OnControlMouseEnter(ByVal Ctrl As MSForms.Control, ByVal Page As MSForms.Page)
    With TextBox1
        .SetFocus
        If Page Is Nothing Then
            .Text = .Text & "> " & "Mouse Entered ...   [ " & Ctrl.Name & " ]" & vbLf
        Else
            'Special case for MultiPages
            .Text = .Text & "> " & "Mouse Entered ...   [ " & Ctrl.Name & "-" & Page.Name & " ]" & vbLf
        End If
    End With
End Sub

Private Sub Form_OnControlMouseLeave(ByVal Ctrl As MSForms.Control, ByVal Page As MSForms.Page)
    With TextBox1
        .SetFocus
        If Page Is Nothing Then
            .Text = .Text & "< " & "Mouse Leave ...   [ " & Ctrl.Name & " ]" & vbLf
        Else
            'Special case for MultiPages
            .Text = .Text & "< " & "Mouse Leave ...   [ " & Ctrl.Name & "-" & Page.Name & " ]" & vbLf
        End If
    End With
End Sub


Note: The code doesn't trap the mouse enter and leave events for Spin and ScrollBar controls as they don't support a mousemove event.
 
Upvote 1
Nice Jafaar. That is the most well behaved MouseLeave/Enter example I have seen to date for MSForms. Not a deal breaker, but did you leave the SpinButton out on purpose? Will it also work with that control?
 
Upvote 0
Nice Jafaar. That is the most well behaved MouseLeave/Enter example I have seen to date for MSForms. Not a deal breaker, but did you leave the SpinButton out on purpose? Will it also work with that control?
Unlike all other standard MSForm controls, the SpinButton and ScrollButton do not have a native MouseMove event which is the event that the class is based on... This could be workedaround using a purely API based approach (one idea comes to mind is by using an API timer coupled with a few IAccessibility or IUIAutomation calls)

Thanks for the feedback.
 
Upvote 0
This is wonderful. I've been trying all kind of methods found on Internet and forums but nothing really satisfying, but this is interesting. How could I modify so that it works for Form Control or Active X on worksheet instead of on UserForm?
 
Upvote 0
This is wonderful. I've been trying all kind of methods found on Internet and forums but nothing really satisfying, but this is interesting. How could I modify so that it works for Form Control or Active X on worksheet instead of on UserForm?
Form controls do not support mousemove event which is the event the code relies on.
ActiveX controls on worksheets do support mousemove events but running a continious loop in the back is not a good idea.. Maybe a windows timer could help but still it would have a bad impact on performance... If a better idea comes to mind, I should post some code.
 
Upvote 0
Form controls do not support mousemove event which is the event the code relies on.
ActiveX controls on worksheets do support mousemove events but running a continious loop in the back is not a good idea.. Maybe a windows timer could help but still it would have a bad impact on performance... If a better idea comes to mind, I should post some code.

I see. I tried running loop and I need to click fast enough CommandButton to trigger click, else ignored ?

Not really an expert but I'd say intermediate in VBA
 
Upvote 0
This works great.

I have 1 issue with it. When I run the command "

VBA Code:
Unload Userform

" it throws an error.

Error: Run-time error '-2147418105 (80010007)':Automation error: The callee (server [not server application]) is not available and disappeared; all connections are invalid. ... If you receive this error while working in the program, there may be a communication issue between the workstation and the server.

When I change the command to
Code:
UserForm.hide

it works correct.

Any ideas how to slove this?
 
Upvote 0
This works great.

I have 1 issue with it. When I run the command "

VBA Code:
Unload Userform

" it throws an error.

Error: Run-time error '-2147418105 (80010007)':Automation error: The callee (server [not server application]) is not available and disappeared; all connections are invalid. ... If you receive this error while working in the program, there may be a communication issue between the workstation and the server.

When I change the command to
Code:
UserForm.hide

it works correct.

Any ideas how to slove this?
Thanks IvoN75 for drawing my attention to this bug.

I have done a quick debug inspection but couldn't properly prevent the error.
That said, since this is a runtime error, it could be easily handled with On Error Resume Next ... Ignoring the error doesn't seem to cause any issues.

VBA Code:
On Error Resume Next
    Call oForm.UserForm_OnControlMouseLeave(Ctrl)
    oForm.Tag = ""
 On Error GoTo 0

Here is the updated file demo :
MouseControlEnterLeaveEvent.xls
 
Upvote 0

Forum statistics

Threads
1,215,365
Messages
6,124,513
Members
449,168
Latest member
CheerfulWalker

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top