我有一个Visual Basic应用程序,我想让它在60秒后执行某些任务,而无需用户点击任何内容或与屏幕交互。
所以基本上我想在用户移动,点击或按下键盘上的键时重置计时器。
我知道如何使用我的表单上的特定控件来执行此操作,但即使焦点超出了我的应用程序,我也希望它能够注册。有什么想法吗?
对此的任何帮助将不胜感激。
答案 0 :(得分:3)
这是一个使用IMessageFilter的快速示例,正如我之前在评论中提到的那样。 IMessageFilter在这里特别受欢迎,因为它适用于所有形式的应用程序,而不仅仅是主要的应用程序:
Public Class Form1
Private WithEvents IdleDetector As IdleTimeout
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
IdleDetector = New IdleTimeout(New TimeSpan(0, 1, 0)) ' one minute timeout duration
Application.AddMessageFilter(IdleDetector)
IdleDetector.Reset()
End Sub
Private Sub IdleDetector_UserIsIdle() Handles IdleDetector.UserIsIdle
' ... do something in here ...
MessageBox.Show("Inactivity detected...locking some feature!")
Button1.Enabled = False
' restart the timeout period?
' IdleDetector.Reset()
End Sub
End Class
Public Class IdleTimeout
Implements IMessageFilter
Public Event UserIsIdle()
Private Const WM_MOUSEMOVE As Integer = &H200
Private Const WM_LBUTTONDOWN As Integer = &H201
Private Const WM_LBUTTONUP As Integer = &H202
Private Const WM_LBUTTONDBLCLK As Integer = &H203
Private Const WM_RBUTTONDOWN As Integer = &H204
Private Const WM_RBUTTONUP As Integer = &H205
Private Const WM_RBUTTONDBLCLK As Integer = &H206
Private Const WM_MBUTTONDOWN As Integer = &H207
Private Const WM_MBUTTONUP As Integer = &H208
Private Const WM_MBUTTONDBLCLK As Integer = &H209
Private Const WM_MOUSEWHEEL As Integer = &H20A
Private Const WM_KEYDOWN As Integer = &H100
Private Const WM_KEYUP As Integer = &H101
Private Const WM_SYSKEYDOWN As Integer = &H104
Private Const WM_SYSKEYUP As Integer = &H105
Private IdleTimeoutDuration As TimeSpan
Private WithEvents tmr As System.Timers.Timer
Private TargetDateTime As DateTime
Private SC As WindowsFormsSynchronizationContext
Public Sub New(ByVal TimeoutDuration As TimeSpan)
SC = System.Windows.Forms.WindowsFormsSynchronizationContext.Current
Me.IdleTimeoutDuration = TimeoutDuration
tmr = New System.Timers.Timer
tmr.Interval = 1000
Me.Reset()
End Sub
Public Sub Reset()
TargetDateTime = DateTime.Now.Add(IdleTimeoutDuration)
tmr.Start()
End Sub
Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
Select Case m.Msg
Case WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP, _
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, _
WM_RBUTTONDOWN, WM_RBUTTONUP, WM_RBUTTONDBLCLK, _
WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MBUTTONDBLCLK
TargetDateTime = DateTime.Now.Add(IdleTimeoutDuration)
End Select
Return False
End Function
Private Sub tmr_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles tmr.Elapsed
If TargetDateTime.Subtract(DateTime.Now).TotalMilliseconds < 0 Then
tmr.Stop()
If Not IsNothing(SC) Then
SC.Post(New System.Threading.SendOrPostCallback(AddressOf RaiseIdleEvent), Nothing)
End If
Else
' This is a one second timer so you could raise a "time out duration left" type event if you wanted to ...
End If
End Sub
Private Sub RaiseIdleEvent(ByVal x As Object)
' ... do not call directly ...
' Called via SC.Post() which puts this in the main UI thread!
RaiseEvent UserIsIdle()
End Sub
End Class
答案 1 :(得分:3)
你必须使用它来获取系统的空闲时间(这是lastinputinfo时间)
<DllImport("user32.dll")> _
Shared Function GetLastInputInfo(ByRef plii As LASTINPUTINFO) As Boolean
End Function
参考here
这是C#,但我希望它可以帮助你。
答案 2 :(得分:1)
我从LastInputInfo获得空闲时间 我使用计时器检索它并每隔500毫秒测试一次,代码看起来像这样(它已经生产了几年了):
Private ATimer As DispatcherTimer
Public Sub New()
....
ATimer = New DispatcherTimer
AddHandler ATimer.Tick, AddressOf Me.ATimer_Tick
ATimer.Interval = TimeSpan.FromMilliseconds(500) 'Checks for idle every 500ms
ATimer.Start()
End Sub
Public Structure LASTINPUTINFO
Public cbSize As Integer
Public dwTime As Integer
End Structure
Public Declare Function GetLastInputInfo Lib "User32.dll" _
(ByRef lii As LASTINPUTINFO) As Boolean
Private Sub ATimer_Tick(ByVal sender As Object, ByVal e As EventArgs)
MyLastInputInfo = New LASTINPUTINFO
MyLastInputInfo.cbSize = Runtime.InteropServices.Marshal.SizeOf(MyLastInputInfo)
' get last input info from Windows
If GetLastInputInfo(MyLastInputInfo) Then ' if we have an input info
' compute idle time
Dim sysIdleTime_ms As Integer = (GetTickCount() - MyLastInputInfo.dwTime)
' ... Now you have the idle time in ms, do whatever you want with it :=)
End Sub