[vb.net] Mausbewegung, Inaktivität

kalle1970

Grünschnabel
Hi, ich habe mir ein kleines Programm geschrieben, das eine bestimme Aktion ausführt, wenn der Benutzer eine bestimmte Zeit nicht aktiv ist (keine Mausbewegung, kein Tastendruck). Soweit klappt auch alles ganz gut, ausser dass diese Eingaben leider nicht systemweit abgefragt werden, sondern nur direkt über dem Form.

die Mausbewegung habe ich bisher so festgestellt:
Code:
Private Sub keyboard_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
    zaehler = startwert
    Label1.Text = zaehler
End Sub
Der Code funktioniert aber nur direkt über dem Form.

Wie frage ich denn die Mausbewegung systemweit ab?
 
Vielen dank schonmal dafür. Nach langem rumgoogeln hab ich herausgefunden dass es wohl 2 Möglichkeiten gibt um Inaktivität festzustellen (Hooks und eine API Funktion namens GetLastInputInfo). Und ich wollte es erstmal mit der API Funktion probieren (mit den Hooks komme ich noch weniger klar).

Zum Thema GetLastInputInfo hab ich das hier auf einer anderen Seite gefunden, was für den betreffenden User auch angeblich funktioniert:

Code:
Public Class Form1
    Private Structure LASTINPUTINFO
        Public cbSize As Integer
        Public dwTime As Integer
    End Structure

    Private Declare Function GetTickCount Lib "kernel32" () As Long
    Private Declare Function GetLastInputInfo Lib "user32" (ByRef plii As LASTINPUTINFO) As Boolean

    Private Sub Form1_Load1(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Command1.Text = "Stop"
        Timer1.Interval = 10  'ms
        Timer1.Enabled = True
    End Sub

    Private Sub Command1_Click1(ByVal sender As Object, ByVal e As System.EventArgs) Handles command1.Click

        If command1.Text = "Start" Then
            Timer1.Start()
            command1.Text = "Stop"
        Else
            Timer1.Stop()
            command1.Text = "Start"
        End If
    End Sub

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Dim lii As LASTINPUTINFO
        lii.cbSize = Len(lii)
        GetLastInputInfo(lii)

        With Label1
            .Text = "system idle (secs): " & FormatNumber((GetTickCount() - lii.dwTime) / 1000, 2)
            .Refresh()
        End With

        Label2.Text = GetTickCount()
        Label3.Text = lii.dwTime
        Label4.Text = lii.cbSize

    End Sub
End Class

Laut seiner Kommentierung, soll im Label 1 wohl eine Zeitangabe in Sekunden stehen. Ich bekomme allerdings Werte wie "2.888.146.463.227,97", welche ich überhaupt nicht nachvollziehen kann. Und ausserdem wird der Wert immer grösser, ob ich die Maus bewege oder nicht.

Die Label 2-4 sind von mir. Damit wollte ich herausfinden wie sich Label1 zusammensetzt. Der Wert Label 3 sieht allerdings schon vielversprechender aus. Ist zwar auch, für mich, ein seltsamer Zahlenwert, der sich aber immerhin nur vergrössert, wenn ich die Maus bewege (auch systemweit).

Ich dachte mir dann, dass man mittels einer IF-Schleife zum Ziel kommen könnte. Irgendwie so: Wenn "lii.dwTime" sich für eine gewisse Zeit nicht ändert, dann starte ein Event. Aber ich steh da völlig aufm Schlauch und mit Sicherheit gibt es da auch elegantere Möglichkeiten.

Kann mir damit bitte jemand helfen?
 
Ich hatte das gleiche Problem und diese Beiträge haben mir sehr geholfen um auf die richtige Lösung zu kommen.

Hier ist mein Code:

Public Class Form1

<Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential)> _
Public Structure LASTINPUTINFO
Public cbSize As UInteger
Public dwTime As UInteger
End Structure

<Runtime.InteropServices.DllImport("USER32.DLL")> _
Private Shared Function GetLastInputInfo(ByRef ii As LASTINPUTINFO) As Boolean
End Function


Public Function GetIdleTime() As Long
Try
Dim lastInPut As New LASTINPUTINFO()
lastInPut.cbSize = CUInt(System.Runtime.InteropServices.Marshal.SizeOf(lastInPut))

If GetLastInputInfo(lastInPut) Then
Dim el As Long = lastInPut.dwTime
Dim ui As Long = (Environment.TickCount - el)

' Overflow
If ui < 0 Then
ui = ui + UInteger.MaxValue + 1
End If

Return ui
Else
Throw New ApplicationException("Timespan")

End If
Catch ex As Exception
Beep()
End Try

End Function

Public Function GetIdleTimeSpan() As TimeSpan
Return New TimeSpan(GetIdleTime() * 10000)
End Function

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Button1.Text = "stop"
Timer1.Interval = 100 'ms
Timer1.Enabled = True
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If Button1.Text = "start" Then
Timer1.Start()
Button1.Text = "stop"
Else
Timer1.Stop()
Button1.Text = "start"
End If
End Sub

Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Label1.Text = Me.GetIdleTimeSpan.ToString
End Sub
End Class

Vielleicht kann ja jemand meine Lösung gebrauchen.

In Laben1 wird eine Timespan ausgegeben, die die Dauer der Inaktivität angibt. Bei jeder Maus- oder Tastatur-Eingabe wird die Timespan wieder auf Null gesetzt und fängt neu an zu zählen.

lg sonja
 
Zurück