Close form if no user action including mouse move over form.

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

This is a curious problem. It seems like it should be quite easy. Of course
a timer is used to determine when form should be closed, but how do you
consistently reset the timer when the mouse is moved over the form.

Normally I would use the MouseMove event to know when the mouse moves over
the form and use that to reset the timer. However, this fails on a form that
has a large number of controls of the form. The Form.MouseMove event will
not fire when the pointer is over a control on the form! Therefore in the
past I built recursive routine to go through the control collections of form
controls and recurse when a container is discovered in the controls
collection. Then for each control found an handler is set for MouseMove to a
method that resets the timer and keeps the form open.

This works but it doesn't seem very graceful. I was wondering if there is
more graceful way to do the same job.

Any help on this is appreciated.

Rob
 
Hi Rob,

see if this can be a way:

Private WithEvents t As New Timer
Private OldMousePos As Point

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
t.Interval = 100
t.Start()
End Sub

Private Sub t_Tick(ByVal sender As Object, ByVal e As
System.EventArgs) Handles t.Tick
If Not Me.Cursor.Position.Equals(OldMousePos) Then
Me.GlobalMouseMove(Me, EventArgs.Empty)
Me.OldMousePos = Me.Cursor.Position
End Sub

'Here do your reset
Sub GlobalMouseMove(ByVal sender As Object, ByVal EventArgs As
EventArgs)
Me.Text = Cursor.Position.X.ToString & "," & _
Cursor.Position.Y.ToString
End Sub


Not sure it's really graceful.

-tom


Rob ha scritto:
 
This is a curious problem. It seems like it should be quite easy. Of course
a timer is used to determine when form should be closed, but how do you
consistently reset the timer when the mouse is moved over the form.

Normally I would use the MouseMove event to know when the mouse moves over
the form and use that to reset the timer. However, this fails on a form that
has a large number of controls of the form. The Form.MouseMove event will
not fire when the pointer is over a control on the form! Therefore in the
past I built recursive routine to go through the control collections of form
controls and recurse when a container is discovered in the controls
collection. Then for each control found an handler is set for MouseMove to a
method that resets the timer and keeps the form open.

This works but it doesn't seem very graceful. I was wondering if there is
more graceful way to do the same job.

Any help on this is appreciated.

Rob


(VB2005)

It's not clear if you are talking about a particular form in your app
or the app itself. If the app, then you can use the Application.Idle
method which will fire when either a long process is complete or the
mouse is not moving - which ever occurs last. Scope of mouse move
detection in this method is application wide without regard to any
particular form or controls.

Gene
 
Yea,

Great (it is in my idea not complete, but the idea)
I was thinking about the hover event, but that would eat much processing.
Your sample does that not.
The only time it could go wrong is if the x and y would be the same; A
chance of 1 in a billion probably.

Cor
 
Good idea Gene,

.... but ... tried it and I must be missing something because does not
seem to work as we expect (?).

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
AddHandler Application.Idle, AddressOf TimeReset
End Sub

Sub TimeReset(ByVal sender As Object, ByVal e As System.EventArgs)
MsgBox("Reset now")
End Sub

Cor, to move the mouse returning exactly to the same start position
within 1/100th of a second would take an enormous speed and incredible
precision :) Anyway your observation make me think about a situation
where the PC is a placed on a noisy place of work where there could be
"vibrations" which make move the mouse slightly. In such a case the
application is essentially idle, but since the vibrations make the
mouse move, it does not appear so. I would be interesting to study an
algorithm which redefines what "idle" means for noisy places ! :)





gene kelley ha scritto:
 
Good idea Gene,

... but ... tried it and I must be missing something because does not
seem to work as we expect (?).

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
AddHandler Application.Idle, AddressOf TimeReset
End Sub

Sub TimeReset(ByVal sender As Object, ByVal e As System.EventArgs)
MsgBox("Reset now")
End Sub

The above code in a simple app would result in a perpetual message box
and no way to exit the app.

This simple example works here using a timer component. If you simply
run the example, the message box displays after 5 seconds. If you run
the example and move the mouse before 5 seconds has elapsed, the timer
restarts.

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
AddHandler Application.Idle, AddressOf TimeReset
Me.Timer1.Interval = 5000

End Sub


Sub TimeReset(ByVal sender As Object, ByVal e As System.EventArgs)
'Start/'Restart the timer
Me.Timer1.Enabled = False
Me.Timer1.Enabled = True

End Sub

Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Timer1.Tick
Me.Timer1.Enabled = False
MessageBox.Show("App has been idle for 5 seconds. App
closing.")
Me.Close()
End Sub


Gene
 
Thank you Gene. Now I understand how the idle event works. Good to know
it. Thanks!

-tommaso

gene kelley ha scritto:
 
Back
Top