Home Image-Pro Automation (Macros, Apps, Reports)

How to know if the mouse is in idle state

Hi Specialist:
               In the app below, when the app is triggered, the figure is imported. But then the mouse is placed in any place of this window. How to set an idle event to know if it's in idle state. Thank you. 
Tagged:

Answers

  • edited February 14
    Hi Stanley,

    It's not clear what are you trying to achieve, can you please provide more details what you are going to do? 
    The application is in an idle state as soon the function you invoked is completed, e.g. the app is loaded.

    Yuri
  • Hi Yuri:
             Thanks for your answer, please let me clarify further. I would like to monitor the mouse event after the processing finished.  Within the red frame, the mouse event can be found involving Mycontrol like the figure. However, when the mouse move outside of this red frame, the mouse event can not be monitored.
    I would like to monitor the mouse (especially idle state) not only within red frame but also outside red frame. Could you please give some advice? Thank you.








  • Hi Stanley,

    So, you want to detect when the mouse is not moving anywhere on the screen, right? If yes, you can use a timer and periodically check the cursor position and detect when the position is not changing during some period. Similar problem is addresses in this post: https://stackoverflow.com/questions/609965/detecting-when-the-mouse-is-not-moving

    Here is how you get cursor position in Image-Pro:
        Public Sub PrintMouseCoordinates
            Dim p As System.Drawing.Point=System.Windows.Forms.Cursor.Position
            Debug.Print( CStr(p.X) & ", " & CStr(p.Y))
        End Sub
    Yuri
  • Hi Yuri:
                Thanks for your direction. I tried to combine timer and cursor position. When the timer is triggered, the position can be exhibited, like below, but the effect is not good. 

    Public Module Module1
        Private aTimer As System.Timers.Timer
    
        Public Function Main()
            
            ' Create a timer and set a two second interval.
            aTimer = New System.Timers.Timer()
            aTimer.Interval = 5000
    
            ' Hook up the Elapsed event for the timer.  
            AddHandler aTimer.Elapsed, AddressOf OnTimedEvent
    
            ' Have the timer fire repeated events (true is the default)
            'aTimer.AutoReset = True
    
            ' Start the timer
            aTimer.Enabled = True
    
    
            Debug.Print("Press the Enter key to exit the program at any time... ")
    
        End Function
    
        Public Sub OnTimedEvent(ByVal source As Object, ByVal e As System.Timers.ElapsedEventArgs)
            MsgBox("The Elapsed event was raised at {" & e.SignalTime & "}")
        End Sub
    End Module
    I tried to apply thread as well, but the easiest example program exists issue in AddressOf. 
    Public Module Module1
        Public Sub CountSheep()
            Dim i As Integer = 1 ' Sheep do not count from 0.
            Do While (True) ' Endless loop.
                Debug.Print("Sheep " & i & " Baah")
                i = i + 1
                System.Threading.Thread.Sleep(1000) 'Wait 1 second.
            Loop
        End Sub
        
        Sub UseThread()
            Dim t As New System.Threading.Thread(AddressOf CountSheep)
            t.Start()
        End Sub
    End Module
    Please give some advice, thank you.



  • edited February 15
    Hi Stenley,

    The idea is to start timer and monitor the displacement of the cursor between the ticks. I've attached the demo project that contains this code:

    Public Module Module1
    
        Private WithEvents _timer As System.Windows.Forms.Timer
        Private _cursorPos As System.Drawing.Point
        Private _mouseIsIdle As Boolean
    
        Public Sub StartMouseMonitoring
            ThisApplication.Output.Show
            ThisApplication.Output.Clear
            _timer =New System.Windows.Forms.Timer
            _timer.Interval=500
            _timer.Start
            _cursorPos=System.Windows.Forms.Cursor.Position
            _mouseIsIdle=True
        End Sub
    
        Public Sub StopMouseMonitoring
            If _timer IsNot Nothing Then
                _timer.Stop
                _timer=Nothing
            End If
        End Sub
    
        Private Sub _timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles _timer.Tick
            Dim p As System.Drawing.Point=System.Windows.Forms.Cursor.Position
            'calculate move btween ticks
            Dim d As Double=System.Math.Sqrt((p.X-_cursorPos.X)*(p.X-_cursorPos.X)+(p.Y-_cursorPos.Y)*(p.Y-_cursorPos.Y))
            _cursorPos=p
            Dim mouseIsIdle As Boolean=(d=0)'check if the mouse is moving
            If mouseIsIdle<>_mouseIsIdle Then
                'mouse started or stopped
                If mouseIsIdle Then
                    ThisApplication.Output($"Mouse stopped at coordinates {p.X} , {p.Y} : on {System.DateTime.Now().TimeOfDay.ToString()}")
                Else
                    ThisApplication.Output($"Mouse started moving on {System.DateTime.Now().TimeOfDay.ToString()}")
                End If
                _mouseIsIdle=mouseIsIdle
            End If
        End Sub
    End Module
    

    When the mouse stops or start moving again, the Output is updated. 

    Mouse started moving on 14:31:05.9750000
    Mouse stopped at coordinates 818 , 464 : on 14:31:09.4710000
    Mouse started moving on 14:31:11.1710000
    Mouse stopped at coordinates 1287 , 236 : on 14:31:13.9720000
    Mouse started moving on 14:31:17.2120000
    Mouse stopped at coordinates 1004 , 505 : on 14:31:17.9710000
    Mouse started moving on 14:31:20.0970000
    Mouse stopped at coordinates 439 , 459 : on 14:31:21.4740000
    Mouse started moving on 14:31:22.5490000


    Load the attached project and run StartMouseMonitoring macro.

    Let me know if it works for you.

    Yuri
  • Thanks Yuri for your help, I have tried this and it works very well.
                       

  • Hi YuriG:
                  I try to make a interactive window like below to prompt user click OK or Cancel. And I hope to add your timer program to continue the program. It means after an idle time, the system will move ahead like the user click the OK. But I found the program seems to wait within the "With" block. Could you please give some advice? Thank you.
                        Try
                            With Measure.Measurements.ToolsCommands.Select(NewMarco)
                                .Prompt = "Press <Enter> or <OK> for live video camera!"
                                '.Tool = emmtool.Circle
                                .Interactive = True
                                .Run(Nothing)
                            End With
    
    
    
                        Catch
    
                            'ACTION FOR CANCEL PRESSED
    
                        End Try
  • Hi Stanley,

    The interactive prompt can be stopped by assigning IsInteracting property of the command to False. The attached project shows how to do that and provides 3 ways of handling workflow: Ok, Cancel, Time Expired:

    Public Module Module1
        Private WithEvents _timer As System.Windows.Forms.Timer
        Private _InteractionCommand As McCommandExtended = Nothing
        Private _InteractionStopped As Boolean = False
    
        Public Sub ShowTimedInteractionPrompt
            _timer = New System.Windows.Forms.Timer
            _timer.Interval=5000'wait 5 seconds
            Dim cm As Object
            cm=Measure.Measurements.ToolsCommands.Select(Nothing)
            _InteractionCommand=cm
            _InteractionStopped=False
            _timer.Start
            Try
                With cm
                    .Prompt = "Press <Enter> or <OK> for live video camera!"
                    '.Tool = emmtool.Circle
                    .Interactive = True
                    .Run(Nothing)
                End With
                If _InteractionStopped Then
                    MsgBox("Wait time expired.")
                Else
                    MsgBox("Ok was hit.")
                End If
            Catch
                MsgBox("Cancel was hit.")
            Finally
            End Try
        End Sub
    
        Private Sub _timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles _timer.Tick
            _InteractionCommand.IsInteracting=False'stop interaction
            _InteractionCommand=Nothing
            _InteractionStopped=True
            _timer.Stop
            _timer=Nothing
        End Sub
    
    End Module
    


    Yuri
  • Thumb Up!!!!
  • Hi Yuri:
               Just an enquiry if it is possible to change the name of "OK" to "live preview"? Thank you.
  • Hi Stanley,

    You can hide Ok button in Automate.ScriptingCommands.Interaction using InteractionButtons=0. Also, this command has own Timeout property, so no need for own timer:

        Public Sub TimedInteractionNoButtons
            Try
                With Automate.ScriptingCommands.Interaction(Nothing)
                    .Prompt="Timed interactive prompt"
                    .InteractionButtons=0'no Ok button
                    .Timeout=5000
                    .Interactive = True
                    .Run(ThisApplication.ActiveImage, Nothing)
                    MsgBox("Wait time expired.")
                End With
            Catch
                MsgBox("Cancel was hit.")
            Finally
            End Try
        End Sub
    
    Using own buttons in interactive prompt is supported, but you have to create own command class and overwrite "ShowInteraction" function, which is not supported on macro level.
    It might be easier to create a button in your app with text you want.

    Yuri
  • Hi Yuri:
               Thanks for your kind answer. I have considered build an app to do interactive job but the effect is not good as I met some issues, it is better to use the one you recommended before. I will just write some more explanations in the interactive window. Thank you so much for solving this issue.
Sign In or Register to comment.