我有一個Visual Basic應用程序,我希望在60秒後沒有用戶單擊任何內容或與屏幕交互時執行某些任務。當鼠標移動到窗口中的任何位置時重置計時器
所以基本上我想在用戶移動,點擊或按下鍵盤上的某個按鍵時重置計時器。
我知道如何用我的表單上的特定控件來做到這一點,但即使焦點位於我的應用程序之外,我也希望它能夠註冊。有任何想法嗎?
任何幫助,這將不勝感激。
我有一個Visual Basic應用程序,我希望在60秒後沒有用戶單擊任何內容或與屏幕交互時執行某些任務。當鼠標移動到窗口中的任何位置時重置計時器
所以基本上我想在用戶移動,點擊或按下鍵盤上的某個按鍵時重置計時器。
我知道如何用我的表單上的特定控件來做到這一點,但即使焦點位於我的應用程序之外,我也希望它能夠註冊。有任何想法嗎?
任何幫助,這將不勝感激。
下面是使用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
「即使焦點位於我的應用程序之外」 –
無論應用程序關注什麼,它都可以工作。 ......但我把這個問題解釋爲一個空閒的探測器**,僅僅是爲了他的應用程序**,但我可以看到它是如何被解釋爲系統範圍的。如果是這種情況,那麼你可以使用SomeNickName的方法,或者實現低級別的鼠標/鍵盤鉤子。 –
你有這個工作得到了系統的空閒時間(這是lastinputinfo時間)
<DllImport("user32.dll")> _
Shared Function GetLastInputInfo(ByRef plii As LASTINPUTINFO) As Boolean
End Function
參考here
這是C#,但我希望它可以幫助你。
我從LastInputInfo獲得空閒時間。
我用一個定時器來檢索並測試它每500ms,代碼如下所示(它已經在生產了好幾年):
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
後,我們得到了一個鼠標點擊 - 我們應該激活主窗口,然後調用彈出窗口中的控件的.Focus()按預期工作。 – user2526236
看看這個:http://stackoverflow.com/a/20434431/897326它回答你的問題嗎? – Neolisk
在自定義類中實現IMessageFilter,並在其WndProc()中捕獲所有需要的「操作」。如果在您的時間限制內未檢測到任何活動,請讓該班級舉辦自定義活動。 –