i want that when user is idle for some particular time and mouse doesnot moves on system than it starts counting time from then ownwards and when user moves mouse then time stops and i can save this time in a varianble
You can use the GetLastInputInfo API call.
The following code is mainly from here: http://pinvoke.net/default.aspx/user32/GetLastInputInfo.html
Imports System.Runtime.InteropServices
Public Class Form1
<StructLayout(LayoutKind.Sequential)> _
Structure LASTINPUTINFO
<MarshalAs(UnmanagedType.U4)> _
Public cbSize As Integer
<MarshalAs(UnmanagedType.U4)> _
Public dwTime As Integer
End Structure
<DllImport("user32.dll")> _
Shared Function GetLastInputInfo(ByRef plii As LASTINPUTINFO) As Boolean
End Function
Dim idletime As Integer
Dim lastInputInf As New LASTINPUTINFO()
Public Function GetLastInputTime() As Integer
idletime = 0
lastInputInf.cbSize = Marshal.SizeOf(lastInputInf)
lastInputInf.dwTime = 0
If GetLastInputInfo(lastInputInf) Then
idletime = Environment.TickCount - lastInputInf.dwTime
End If
If idletime > 0 Then
Return idletime / 1000
Else : Return 0
End If
End Function
Private sumofidletime As TimeSpan = New TimeSpan(0)
Private LastLastIdletime As Integer = 0
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim it As Integer = GetLastInputTime()
If LastLastIdletime > it Then
Label1.Text = "IDLE STATE CHANGED!"
sumofidletime = sumofidletime.Add(TimeSpan.FromSeconds(LastLastIdletime))
Label2.Text = "Sum of idle time: " & sumofidletime.ToString
Else
Label1.Text = GetLastInputTime()
End If
LastLastIdletime = it
End Sub
End Class
This code displays the seconds the user has been idle since the last input action in the label on every timer tick. It also checks if the idle state has changed. So at this point you can react to it and save the LastLastIdletime as the amount of time in seconds that the user was inactive.
To prevent having to handle this for many controls you can rearrange things a bit and cache the information needed to know if cursor has moved and how long the idle time is, to do this you need a Point variable and a Date variable. The Timer needs to tick all the time. In addition, to balance the cursor Show/Hide calls you need a variable to keep track of its visibility state. Here is the complete code sample:
Private loc As Point, idle As Date, hidden As Boolean
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If loc <> Cursor.Position Then
If hidden Then
Cursor.Show()
hidden = False
End If
loc = Cursor.Position
idle = Date.Now
ElseIf Not hidden AndAlso (Date.Now - idle).TotalSeconds > 3 Then
Cursor.Hide()
hidden = True
End If
End Sub
This Timer can tick each 1/2-1 seconds depending on how responsive you want it, the idle time is set to 3 seconds. The code should be easy to understand when you read it and give it some thought, if not ask
Related
I have a small media player application I've programmed which works really well.
I've even managed an on screen remote control (obviously just a Form with Buttons made to look like a virtual remote control) and yes I've also integrated an Arduino to be able to use a real remote control, but forget the Arduino remote control just for now my question is about the Virtual remote control I'm trying to build.
Programming a Button is quite elementary: it's one of the first things we learn in Vb.net, but that's just in a single click scenario.
If I look at a real TV remote, I can either click (most common with volume buttons) the volume up or down and the response is either that the volume goes up or down by one unit, or I can hold the same button down and it repeats the process changing the unit several times up or down depending on how long before I release the button again.
How would I achieve this?
I have tried googling this but everything I get back as a search result talks about a physical mouse button as apposed to what I need which is a Button control.
An example of an UserControl that provides the functionality of Up/Down spin buttons.
It uses two standard Buttons, a Label and a Timer.
To set it up, add a new UserControl to the Project:
Set its BackColor to Color.Transparent
Add two Buttons, select both and add event handlers to the MouseDown, MouseUp, KeyDown and KeyUp events (selecting both, you'll add 4 method)
Two Unicode chars (U+25B2 and U+25BC) are used to show the arrows. Setup the Buttons' Font size and Color as required (the sample UC uses Segoe UI as Font).
Anchor the upper Button to Left/Top/Right
Anchor the lower Button to Left/Bottom/Right
Anchor the Label to Left/Right
A Timer is created in the UC constructor, its Interval value set to 300. This value represents the initial speed of the increment when a mouse Button or keyboard key is held down. It's decremented each time the Timer ticks until it reaches a threshold defined by the UC's Speed public property (which is internally limited to the (1:10) range).
The maximum and minimum increment are defined by the UC's Min and Max public properties
The Value public property gets or sets the current increment.
The Timer is started when a Mouse Button or a Keyboard key are pressed and stopped when they're released. When the Timer.Tick event is raised, the Timer.Interval is decreased by 25ms until the max Speed value is reached. Since the initial value is set to 300ms and the maximum Speed is limited to 10, the minimum Interval value is 50ms, which is close to the System.Windows.Form.Timer official resolution.
The minimum Interval needs to be considered if these values are changed, to avoid overlapping Tick events.
This is how it works:
Imports System.Windows.Forms
Public Class SpinButtons
Private buttonsTimer As Timer = Nothing
Private timerThrottle As Integer = 0
Private timerIncrement As Integer = 0
Private m_Speed As Integer = 10
Private m_Value As Integer = 0
Public Sub New()
InitializeComponent()
Me.components = New System.ComponentModel.Container()
buttonsTimer = New Timer With {.Interval = 300}
Me.components.Add(buttonsTimer)
End Sub
Public Property Max As Integer = 100
Public Property Min As Integer = 0
Public Property Speed As Integer
Get
Return m_Speed
End Get
Set
m_Speed = Math.Max(Math.Min(Value, 10), 1)
End Set
End Property
Public Property Value As Integer
Get
Return m_Value
End Get
Set
m_Value = Value
SetIncrementValue()
End Set
End Property
Private Sub buttonsTimer_Tick(sender As Object, e As EventArgs)
SetIncrementValue()
If timerThrottle <= m_Speed Then
timerThrottle += 1
buttonsTimer.Interval -= 25
End If
End Sub
Private Sub btnUp_MouseDown(sender As Object, e As MouseEventArgs) Handles btnUp.MouseDown, btnDown.MouseDown
ButtonPressed(DirectCast(sender, Button))
SetIncrementValue()
End Sub
Private Sub btnUp_MouseUp(sender As Object, e As MouseEventArgs) Handles btnUp.MouseUp, btnDown.MouseUp
ButtonReleased(DirectCast(sender, Button))
End Sub
Private Sub btnUp_KeyDown(sender As Object, e As KeyEventArgs) Handles btnUp.KeyDown, btnDown.KeyDown
ButtonPressed(DirectCast(sender, Button))
SetIncrementValue()
End Sub
Private Sub btnUp_KeyUp(sender As Object, e As KeyEventArgs) Handles btnUp.KeyUp, btnDown.KeyUp
ButtonReleased(DirectCast(sender, Button))
End Sub
Private Sub SetIncrementValue()
m_Value += timerIncrement
m_Value = Math.Max(Math.Min(m_Value, Max), Min)
lblCounter.Text = m_Value.ToString()
End Sub
Private Sub ButtonPressed(btn As Button)
btn.ForeColor = Color.LawnGreen
timerIncrement = If(btn Is btnUp, 1, -1)
buttonsTimer.Enabled = True
End Sub
Private Sub ButtonReleased(btn As Button)
buttonsTimer.Enabled = False
buttonsTimer.Interval = 300
timerThrottle = 0
timerIncrement = 0
btn.ForeColor = Color.White
End Sub
Protected Overrides Sub OnFontChanged(e As EventArgs)
MyBase.OnFontChanged(e)
Me.btnUp.Font = Me.Font
Me.btnDown.Font = Me.Font
End Sub
Protected Overrides Sub OnResize(e As EventArgs)
MyBase.OnResize(e)
Me.MinimumSize = New Size(CInt(Me.Font.Size * 2), Me.btnUp.Height + Me.btnDown.Height + lblCounter.Height)
End Sub
End Class
Writing the title to try and explain my query I think was harder than the problem I'm actually facing :) - Anyway on to the question.
So I have a 20 second timer but I want two different things to happen on the first and second 10 seconds. Specifically to change the active tab.
So I thought to myself I'll just write an if Statement in the timer tick event that if it = 10 seconds to change to the second tab and when it hits 0 to switch back to the first, then to restart the timer.
Below is my code but nothing happens, I think the problem lies with reading the current remaining time.
Private timeLeft2 As Integer
Private Sub timerCountdown2()
timeLeft2 = 20
End Sub
Private Sub tabTimer_Tick(sender As Object, e As EventArgs) Handles tabTimer.Tick
If timeLeft2 = 10 Then
TabControlVertical1.SelectTab(1)
End If
If timeLeft2 = 0 Then
TabControlVertical1.SelectTab(0)
tabTimer.Stop()
tabTimer.Start()
End If
End Sub
The properties of my timer are enabled = true and Interval = 1000
What am I doing wrong?
You should set the timer to trigger the Tick event every 10 seconds, not every 20 (or 1 as by your edit above).
Every time the Tick event is triggered, you look at the value of a global boolean variable.
If this variable is true you execute the code reserved for the first 10 seconds and invert the value of the boolean. When the timer triggers again, you execute the code for the second case and invert again the value of the boolean
So, somewhere in your code or in the designer set the tabTimer interval to 10 seconds
tabTimer.Interval = 10000
and declare a global boolean variable (In the same forms class probably)
Private tabSwitcher as Boolean = True
Now the Tick event could be written as:
(no need to stop the timer if this process needs to continue)
Private Sub tabTimer_Tick(sender As Object, e As EventArgs) Handles tabTimer.Tick
If tabSwitcher = True Then
TabControlVertical1.SelectTab(1)
else
TabControlVertical1.SelectTab(0)
End If
tabSwitcher = Not tabSwitcher
End Sub
This is what I think you are asking:
do something in 10 timer ticks - timer set to 1000
do something else 10 timer ticks later
repeat
Try this
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Static ct As Integer = 0
ct += 1
If ct = 10 Then
'do 10 stuff here
Debug.WriteLine("10")
ElseIf ct = 20 Then
'do 20 stuff here
Debug.WriteLine("20")
'then reset ct <<<<<<<<<<<<
ct = 0
End If
End Sub
Friend Class timerCtrl : Inherits Timer
Private ReadOnly tickFunc As EventHandler = Nothing
Friend Sub New(ByRef theFunc As EventHandler, ByVal theInterval As Integer, Optional ByVal autoStart As Boolean = True)
tickFunc = theFunc
Interval = theInterval
AddHandler Tick, tickFunc
If (autoStart) Then Start()
End Sub
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
RemoveHandler Tick, tickFunc
End If
MyBase.Dispose(disposing)
End Sub
End Class
Friend Class TabClass
Private timerStep As Boolean = False
Private timerTabs As timerCtrl = Nothing
Friend Sub New()
timerTabs = New timerCtrl(AddressOf timerTabsTick, 10000)
End Sub
Private Sub timerTabsTick(ByVal sender As Object, ByVal e As EventArgs)
timerStep = Not timerStep
If timerStep Then
' condition 1
Else
' condition 2
End If
End Sub
End Class
a simple timer helper class for abstraction. to kill the timer, not just .Stop it, use timerTabs.Dispose(). eliminates the need to detach the event handler separately.
Seems to me that your timer is never getting to the value you are asking for in the if statements due to the fact that you have set the timer to the value of 20.
Also, I've use visual basics and am not to sure but doens't it need to be timeleft2.value?
Also, by stoping and starting the timer, it isn't actually restarting the timer, when you stop it say on 15 secs, and the restart, the timer restarts from 15 secs.
Try this.
If timeLeft2.Value = 10 Then
TabControlVertical1.SelectTab(1)
else if timeLeft2.Value = 0 Then
TabControlVertical1.SelectTab(0)
tabTimer.Stop()
timeLeft2.value = 0
tabTimer.Start()
End If
I'm trying to create a thread so when I click a button it creates a new PictureBox from a class, this is how far I've got but nothing comes up on the screen at all.
Form1 code:
Public Class Form1
Private pgClass As New SecondUIClass
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
pgClass = New SecondUIClass
pgClass.x += 100
pgClass.thread()
End Sub
End Class
Class Code:
Imports System.Threading
Public Class SecondUIClass
Public Const count As Integer = 1000
Public emeny(count - 1) As PictureBox
Public counter As Integer = 0
Public x As Integer = 0
Private trd As Thread
Public Sub thread()
trd = New Thread(AddressOf NewUIThread)
trd.SetApartmentState(ApartmentState.STA)
trd.IsBackground = False
trd.Start()
End Sub
Private Sub NewUIThread()
emeny(counter) = New PictureBox
emeny(counter).BackColor = Color.Red
emeny(counter).Visible = True
emeny(counter).Location = New System.Drawing.Point(x, 100)
emeny(counter).Size = New System.Drawing.Size(10, 50)
Form1.Controls.Add(emeny(counter))
For z = 0 To 13
emeny(counter).Location = New Point(emeny(counter).Location.X + 10, emeny(counter).Location.Y)
Application.DoEvents()
Threading.Thread.Sleep(100)
Next
counter += 1
End Sub
End Class
I have posted something similar before on here but it was different, the pictureBoxes were showing on the screen but I was trying to get them to move at the same time but they wouldn't move, they only moved one at a time. The question that I asked before was this Multi threading classes not working correctly
I made a few assumptions for this answer so it may not work for you out of the box but I think it will put you on the right track without using any Thread.Sleep calls because I personally don't like building intentional slows to my apps but that's a personal preference really.
So For my example I just used a bunch of textboxes because I didn't have any pictures handy to fiddle with. But basically to get it so that the user can still interact with the program while the moving is happening I used a background worker thread that is started by the user and once its started it moves the textboxes down the form until the user tells it to stop or it hits an arbitrary boundary that I made up. So in theory the start would be the space bar in your app and my stop would be adding another control to the collection. For your stuff you will want to lock the collection before you add anything and while you are updating the positions but that is up to your discretion.
So the meat and potatoes:
in the designer of the form I had three buttons, btnGo, btnStop and btnReset. The code below handles the click event on those buttons so you will need to create those before this will work.
Public Class Move_Test
'Flag to tell the program whether to continue or to stop the textboxes where they are at that moment.
Private blnStop As Boolean = False
'Worker to do all the calculations in the background
Private WithEvents bgWorker As System.ComponentModel.BackgroundWorker
'Controls to be moved.
Private lstTextBoxes As List(Of TextBox)
'Dictionary to hold the y positions of the textboxes.
Private dtnPositions As Dictionary(Of Integer, Integer)
Public Sub New()
' Default code. Must be present for VB.NET forms when overwriting the default constructor.
InitializeComponent()
' Here I instantiate all the pieces. The background worker to do the adjustments to the position collection, the list of textboxes to be placed and moved around the form
' and the dictionary of positions to be used by the background worker thread and UI thread to move the textboxes(because in VB.NET you can not adjust controls created on the UI thread from a background thread.
bgWorker = New System.ComponentModel.BackgroundWorker()
Me.lstTextBoxes = New List(Of TextBox)
Me.dtnPositions = New Dictionary(Of Integer, Integer)
For i As Integer = 0 To 10
Dim t As New TextBox()
t.Name = "txt" & i
t.Text = "Textbox " & i
'I used the tag to hold the ID of the textbox that coorelated to the correct position in the dictionary,
' technically you could use the same position for all of them for this example but if you want to make the things move at different speeds
' you will need to keep track of each individually and this would allow you to do it.
t.Tag = i
dtnPositions.Add(i, 10)
'Dynamically position the controls on the form, I used 9 textboxes so i spaced them evenly across the form(divide by 10 to account for the width of the 9th text box).
t.Location = New System.Drawing.Point(((Me.Size.Width / 10) * i) + 10, dtnPositions(i))
Me.lstTextBoxes.Add(t)
Next
'This just adds the controls to the form dynamically
For Each r In Me.lstTextBoxes
Me.Controls.Add(r)
Next
End Sub
Private Sub Move_Test_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
'Don't need to do anything here. Placeholder
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message)
End Try
End Sub
Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
Try
If Not bgWorker.IsBusy Then
'User starts the movement.
bgWorker.RunWorkerAsync()
End If
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message)
End Try
End Sub
Private Sub btnReset_Click(sender As Object, e As EventArgs) Handles btnReset.Click
Try
'Reset the positions and everything else on the form for the next time through
' I don't set the blnStop value to true in here because it looked cooler to keep reseting the textboxes
' and have them jump to the top of the form and keep scrolling on their own...
For Each r In Me.lstTextBoxes
r.Location = New System.Drawing.Point(r.Location.X, 10)
Next
For i As Integer = 0 To dtnPositions.Count - 1
dtnPositions(i) = 10
Next
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message)
End Try
End Sub
Private Sub bgWorker_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgWorker.DoWork
Try
'This is where we do all the work.
' For this test app all its doing is scrolling through each value in the dictionary and incrementing the value
' You could make the dictionary hold a custom class and have them throttle themselves using variables on the class(or maybe travel at an angle?)
For i As Integer = 0 To dtnPositions.Count - 1
dtnPositions(i) += 1
Next
Catch ex As Exception
blnStop = True
End Try
End Sub
Private Sub bgWorker_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgWorker.RunWorkerCompleted
Try
'Once the background worker is done updating the positions this function scrolls through the textboxes and assigns them their new positions.
' We have to do it in this event because we don't have access to the textboxes on the backgroun thread.
For Each r In Me.lstTextBoxes
r.Location = New System.Drawing.Point(r.Location.X, dtnPositions(CInt(r.Tag)))
Next
'use linq to find any textboxes whose position is beyond the threshhold that signifies they are down far enough.
' I chose the number 100 arbitrarily but it could really be anything.
Dim temp = From r In Me.lstTextBoxes Where r.Location.Y > (Me.Size.Height - 100)
'If we found any textboxes beyond our threshold then we set the top boolean
If temp IsNot Nothing AndAlso temp.Count > 0 Then
Me.blnStop = True
End If
'If we don't want to stop yet we fire off the background worker again and let the code go otherwise we set the stop boolean to false without firing the background worker
' so we will be all set to reset and go again if the user clicks those buttons.
If Not Me.blnStop Then
bgWorker.RunWorkerAsync()
Else
Me.blnStop = False
End If
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message)
End Try
End Sub
Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
Try
'The user clicked the stop button so we set the boolean and let the bgWorker_RunWorkerCompleted handle the rest.
Me.blnStop = True
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message)
End Try
End Sub
End Class
Theres a lot of code there but a lot of it is comments and I tried to be as clear as possible so they are probably a little long winded. But you should be able to plop that code on a new form and it would work without any changes. I had the form size quite large (1166 x 633). So I think that's when it works best but any size should work(smaller forms will just be more cluttered).
Let me know if this doesn't work for your application.
This is a problem that is well suited to async/await. Await allows you to pause your code to handle other events for a specific period of time..
Private Async Function Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) As Task Handles Button1.Click
pgClass = New SecondUIClass
pgClass.x += 100
await pgClass.NewUIThread()
End Sub
End Class
Class Code:
Imports System.Threading
Public Class SecondUIClass
Public Const count As Integer = 1000
Public emeny(count - 1) As PictureBox
Public counter As Integer = 0
Public x As Integer = 0
Private Async Function NewUIThread() As Task
emeny(counter) = New PictureBox
emeny(counter).BackColor = Color.Red
emeny(counter).Visible = True
emeny(counter).Location = New System.Drawing.Point(x, 100)
emeny(counter).Size = New System.Drawing.Size(10, 50)
Form1.Controls.Add(emeny(counter))
For z = 0 To 13
emeny(counter).Location = New Point(emeny(counter).Location.X + 10, emeny(counter).Location.Y)
await Task.Delay(100) 'The await state machine pauses your code here in a similar way to application.doevents() until the sleep has completed.
Next
counter += 1
End Sub
End Class
I am trying to create a timer that will countdown from the specified time.
The user enters a time and clicks a button.
The button click opens a second form that has a timer in it.
Every time the timer ticks, the time decreases and the time left is displayed in a textbox on form2 (textbox.text = timeLeft).
However, the textbox will never actually update. It remains blank, and the only time that assigning a new value to the .text property will actually work is if I raise an event (for example clicking a button that will change the .text property of the textbox)
*Here is the code for the timer class
Public Class CountdownTimer
Private timeAtStart As Integer
Private timeLeft As Integer
Public Sub StartTimer(ByVal time As Integer)
timeAtStart = time
timeLeft = timeAtStart
Timer1.Enabled = True
End Sub
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If timeLeft > 0 Then
timeLeft = timeLeft - 1
txtTimeLeft.Text = timeLeft.ToString
Else
Timer1.Stop()
txtTimeRemaining.Text = "Time!"
txtTimeRemaining.ForeColor = Color.Red
End If
End Sub
End Class
And here is how I call it:
Dim timer As New CountdownTimer
timer.Show()
CountdownTimer.StartTimer(CInt(txtSetTime.Text))
Your code is calling the (form) class not the instance, and I cant see where Timer1 is properly referenced for an independant reusable class. Here is one way to implement a CountDown class that will work with other forms....
Friend Class CountdownTimer
Private timeAtStart As Integer
Private timeLeft As Integer
Private WithEvents Timer1 As New Timer
Private txtTimeLeft as TextBox
Public Sub New(TargetTB as TextBox)
txtTimeLeft= TargetTB
End Sub
Public Sub StartTimer(ByVal time As Integer, timeLength as Integer)
timeAtStart = time
timeLeft = timeLength
Timer1.Enabled = True
End Sub
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs)_
Handles Timer1.Tick
' just dislaying time left
If timeLeft > 0 Then
timeLeft = timeLeft - 1
txtTimeLeft.Text = timeLeft.ToString
Else
Timer1.Stop()
txtTimeLeft.Text = "Time!"
txtTimeLeft.ForeColor = Color.Red
End If
End Sub
End Class
How to use it:
Dim CountDn As New CountdownTimer(frm.TextBoxToUse)
' use the INSTANCE name not the class name!!!!
'CountdownTimer.StartTimer(CInt(txtSetTime.Text))
CountDn.StartTimer(CInt(txtSetTime.Text))
If it displays the result after the timer has completed, i think you should use the
Application.DoEvents()
method to see the update immediately. It actually works with Windows Forms. What have you tried, so i can help further
You do realize that when you are counting down you are setting a different textbox than when it is complete, right?
txtTimeLeft.Text
VS
txtTimeRemaining.Text
Note: Timers run on the same thread as the UI so if you computer (or program) gets busy, the timer will NOT tick at exact intervals. If you are worried about small variances in your timer, you should compare the difference of your computer time during each tick event to determine how much time had passed.
Dim TS = TimeSpan = Now.Subtract(StartingTime)
Try refreshing the text boxes after each update:
So after
txtTimeLeft.Text = timeLeft.ToString
Add
txtTimeLeft.Refresh
This is your problem:
Dim timer As New CountdownTimer
timer.Show()
CountdownTimer.StartTimer(CInt(txtSetTime.Text))
You instantiate a new object called timer, but then start the timer on the CountdownTimer object
You need to change your code to this:
Dim timer As New CountdownTimer
timer.Show()
timer.StartTimer(CInt(txtSetTime.Text))
I would like to stop the timer whenever a mouse stops moving inside a groupbox
As of now, I start the timer when the mouse hover at the groupbox and stops it when it leaves the group box.
Private Sub gbxMouseMap_MouseHover(sender As Object, e As System.EventArgs) Handles gbxMouseMap.MouseHover
Timer.Start()
End Sub
Private Sub gbxMouseMap_MouseLeave(sender As Object, e As System.EventArgs) Handles gbxMouseMap.MouseLeave
Timer.Stop()
End Sub
In the MouseMove event set a class varible named LastMoveTime to the current timer elapsed time. In the MouseHover event check to see if LastMoveTime has reached the timeout period, if so stop the timer.
I will get you started...
Private LastMoveTime As DateTime
Private MouseTimeoutMilliseconds as Integer = 500
'put inside hover
If LastMoveTime.AddMilliseconds(MouseTimeoutMilliseconds) < Now Then
Timer.Stop()
Else
Timer.Start()
End if
To prevent having to handle this for many controls you can rearrange things a bit and cache the information needed to know if cursor has moved and how long the idle time is, to do this you need a Point variable and a Date variable. The Timer needs to tick all the time. In addition, to balance the cursor Show/Hide calls you need a variable to keep track of its visibility state. Here is the complete code sample:
Private loc As Point, idle As Date, hidden As Boolean,
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If loc <> Cursor.Position Then
If hidden Then
Cursor.Show()
hidden = False
End If
loc = Cursor.Position
idle = Date.Now
ElseIf Not hidden AndAlso (Date.Now - idle).TotalSeconds > 3 Then
Cursor.Hide()
hidden = True
End If
End Sub
This Timer can tick each 1/2-1 seconds depending on how responsive you want it, the idle time is set to 3 seconds. The code should be easy to understand when you read it and give it some thought, if not ask