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

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
 
T

tommaso.gastaldi

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:
 
G

gene kelley

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
 
C

Cor Ligthert [MVP]

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
 
T

tommaso.gastaldi

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:
 
G

gene kelley

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
 
T

tommaso.gastaldi

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

-tommaso

gene kelley ha scritto:
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top