0

ユーザーが何もクリックしたり画面を操作したりせずに 60 秒が経過した後に、特定のタスクを実行させたい Visual Basic アプリケーションがあります。

したがって、基本的には、ユーザーがキーボードのキーを移動、クリック、または押すたびにタイマーをリセットしたいと考えています。

フォームの特定のコントロールでこれを行う方法は知っていますが、フォーカスがアプリケーションの外にある場合でも登録したいと思います。何か案は?

これについての助けをいただければ幸いです。

4

3 に答える 3

3

システムのアイドル時間 (lastinputinfo 時間) を取得するには、これを使用する必要があります。

<DllImport("user32.dll")> _
Shared Function GetLastInputInfo(ByRef plii As LASTINPUTINFO) As Boolean
End Function

ここを参照

C#ですが参考になれば幸いです。

于 2013-12-12T20:24:12.703 に答える
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
于 2013-12-12T20:15:37.243 に答える
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
于 2013-12-13T13:40:26.643 に答える