Solved

Detect user inactivity in a VB.NET Windows Application (multiple forms)

Posted on 2004-10-12
7
7,047 Views
Last Modified: 2012-06-22
I have a large VB.NET application with over 50 forms. There are ~100 functions that require a username and password to commit, and users are finding it a pain to have to continually type their usernames and passwords at each stage.
I want to move to a model that only prompts for a username & password if the application has been inactive (no keyboard of mouse events) for over 3
minutes.
Since I have a large amount of forms and controls, resetting a timer from each individual control is a nightmare. Is there a way of detecting keypress and mouse events across all contols and forms in an application?
I've seen refences to the Application.idle event but no examples on how to call it.

Lanson.
0
Comment
Question by:lanson
7 Comments
 

Expert Comment

by:wayko621
ID: 12286695
A process is said to be idle when its main window is waiting for input from the system. In order to test the process for its idle state, you must first bind a Process component to it. You can call the WaitForInputIdle method before having the target process perform an action.

The WaitForInputIdle method instructs a Process component to wait for the associated process to enter an idle state. The method is useful, for example, when your application waits for a process to finish creating its main window before communicating with that window. The WaitForInputIdle method only works with processes that have a user interface.

To wait for a process to complete an action

Associate an instance of a Process component to a process you want to start. For more information, see Starting Processes.
Start the process by calling the Start method.
Call the appropriate WaitForInputIdle method:
WaitForInputIdle() - instructs the Process component to wait indefinitely for the associated process to enter an idle state.
WaitForInputeIdle(Int32) - instructs the Process component to wait the specified number of milliseconds for an associated process to enter an idle state.
The following example shows how to call the WaitForInputIdle method to wait for Notepad to complete loading before assigning its modules property to an empty array.

' Visual Basic
Dim myProcess as New Process()
myProcess.Start("Notepad.exe")
myProcess.WaitForInputIdle()

// C#
Process myProcess;
myProcess = Process.Start("Notepad");
myProcess.WaitForInputIdle();

maybe this can help =)

You can try the raiseevent also ill get u a code when i test it out
0
 
LVL 28

Accepted Solution

by:
iboutchkine earned 250 total points
ID: 12288955
Private Sub OnApplicationIdle( _
    ByVal sender As Object, ByVal e As System.EventArgs)
i+= 1
       If Time1 > 100 Then
           MessageBox.Show("Application is idle")
           i = 0 ' reset i
       End If

End Sub

To handle the event you must add the event handler.

AddHandler Application.Idle Addressof OnApplicationIdle

0
 
LVL 18

Expert Comment

by:armoghan
ID: 12296074
0
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
LVL 1

Author Comment

by:lanson
ID: 12306943
iboutchkine

Thanks for the info, but I have another question:
1) I tried the code as you supplied it and the idle event is firing constantly while the application is idle. This is fine , if I can find a way to detect a mouse or keyboard event , which I will use to reset the timeout timer. I can't use the keypress events etc as I have thousands of individual controls.
Can I detect what event just finished before the Idle event was called?
(does the e parameter of the function hold this info?)


Regards,
  Lanson.
0
 
LVL 28

Expert Comment

by:iboutchkine
ID: 12308102
Put the timer reset to mouse move event
0
 
LVL 1

Author Comment

by:lanson
ID: 12316850
iboutchkine,
I need to track more than mouse movements, as a lot of the users would be performing data entry using just keyboard and tabs.

I've come up with the following solution:
1) Implement the event handler as you suggested above
2) Use the user32 windows api to detect mouse movement and keypress. The problem with this method is that all mouse movements and keypresses, across all applications are detected, so I use the GetForegroundWindow() and GetWindowText functions of the API to determin if the events happen while my app has focus - ignoring them if it dosn't have focus. All I have to ensure is that the Window Text for all my forms begins with the same Title (e.g MyApp - Main , MyApp - Edit etc)

Example:
 
' Declare form1 as public , as this will hold the idle event code and had to be loaded at all times (can be hidden)

Module Module1

    Public form1 As New form1
    Public intcnt As Integer
    Public LogoutTimer As Date
   
End Module


Public Class Form1

    Inherits System.Windows.Forms.Form
    Public i As Integer
    Public ctrCurr As Control
    Structure POINTAPI
        Public mouseX As Long
        Public mouseY As Long
    End Structure


    Declare Function GetCursorPos Lib "user32" (ByRef lpPoint As POINTAPI) As Integer

    Public Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vKey As Long) As Integer
    Public Declare Function GetActiveWindow Lib "user32" () As Integer
    Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Integer, ByVal lpString As String, ByVal cch As Integer) As Integer
    Public Declare Function GetForegroundWindow Lib "user32" () As Integer

    Public posOld As POINTAPI
    Public posNew As POINTAPI

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


        ' Associate an event handler with an event.
        AddHandler Application.Idle, AddressOf OnApplicationIdle


    End Sub

   
    Sub OnApplicationIdle(ByVal sender As Object, ByVal e As System.EventArgs)



        Dim x As Long

        x = DateDiff(DateInterval.Minute, LogoutTimer, Now)
        If x > 3 Then
            MsgBox("Timeout!")
            LogoutTimer = Now
        Else

        End If

        Dim foreground_hwnd As Integer

        Dim length As Long

        foreground_hwnd = GetForegroundWindow()

        strWindowText = Space$(1024)
        length = GetWindowText(foreground_hwnd, strWindowText, Len(strWindowText))

        strWindowText = strWindowText.Substring(0, length)

        If InputCheck() Then


            x = DateDiff(DateInterval.Second, LogoutTimer, Now)
            If x > 10 Then
                MsgBox("Timeout!")
            Else
                LogoutTimer = Now

            End If
        End If





    End Sub







 

    Public Function InputCheck() As Boolean
        Dim i As Integer

        'Get the current mouse cursor coordinates
        Call GetCursorPos(posNew)
        'Compare with old coordinates
        'Only flag if the curent window is part of the application MyApp (Window Title)
        If ((posNew.mouseX <> posOld.mouseX) Or (posNew.mouseY <> posOld.mouseY)) And Mid(strWindowText, 1, 5) = "MyApp" Then
            posOld = posNew
            InputCheck = True
            Exit Function
        End If
        'Check keys state
        For i = 0 To 255
            'Only flag if the curent window is part of the application MyApp (Window Title)
            If (GetAsyncKeyState(i) And &H8001) <> 0 And Mid(strWindowText, 1, 5) = "MyApp" Then
                InputCheck = True
                Exit Function
            End If
        Next i
        InputCheck = False
    End Function





End Class

'This Function detects any movement/keypress within the application

    Public Function InputCheck() As Boolean
        Dim i As Integer

        'Get the current mouse cursor coordinates
        Call GetCursorPos(posNew)
        'Compare with old coordinates
        'Only flag if the curent window is part of the application MyApp (Window Title)
        If ((posNew.mouseX <> posOld.mouseX) Or (posNew.mouseY <> posOld.mouseY)) And Mid(strWindowText, 1, 5) = "MyApp" Then
            posOld = posNew
            InputCheck = True
            Exit Function
        End If
        'Check keys state
        For i = 0 To 255
            'Only flag if the curent window is part of the application MyApp (Window Title)
            If (GetAsyncKeyState(i) And &H8001) <> 0 And Mid(strWindowText, 1, 5) = "MyApp" Then
                InputCheck = True
                Exit Function
            End If
        Next i
        InputCheck = False
    End Function





0
 
LVL 15

Expert Comment

by:x77
ID: 33883615
There are some methods to handle Hook to Keyboard / mouse events, but this is very complex.
You have many forms on your app, and you do´nt want recode each form to detect mouse / keyboard activity.

I think you can write a simple class AppForm that detects activity (mouse / keyboard) overriding OnMouseMove and ProcessDialogKey.

You ca set a global var to time action is generated.
Note that time compsuption for this code is minimal.

Then on Application idle event you verify  

    If (Now - GlobalLastKeyboardMouseAction).TotalMinutes > 20 Then
        --- Write Code for Time exceded Here

Now you can change for each form from
    Inherites System.Windows.Form
to
    Inherits AppForm  
0

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Close tabpage of custom control 9 33
Advice in Xamarin 21 78
VB.NET 2008 Populate DataModel with DataTable 44 28
VB: Convert 2 dates to specific format 24 48
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

815 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now