One of the requriements I thought up for my stop watch, is to detect if the system has been idle for a long time. If it has been idle for say half an hour, and clock is running, then it should alert the user and pause. This is to prevent the clock from counting incase I forget to pause it or stop and leave the computer for some reason.

There are two ways to achieve this, One is to monitor the system for the keyboard/mouse events and keep a count of time elapsed, the other is to use the win32 api GetLastInputInfo().

GetLastInputInfo : This is a very simple method to get the system idle time. Let us have a look at the function prototype.

BOOL GetLastInputInfo(PLASTINPUTINFO plii);

The function accepts a pointer to the LASTINPUTINFO structure, which is described as below.

typedef struct tagLASTINPUTINFO
{
   UINT cbSize;
   DWORD dwTime;
} LASTINPUTINFO, *PLASTINPUTINFO;

As you can see it is a very basic structure, before calling the GetLastInputInfo function we have to initialise the cbSize variable. This is easily achieved by sizeof(LASTINPUTINFO). The function returns the last tick count of any mouse or keyboard events. The tick count is the number of milliseconds which have elapsed since the sytem was booted up. i.e. the same type of information returned by GetTickCount() function. For more information on tick count, look up GetTickCount() function on msdn.

Once we have this info, it is very easy to compare it with the current time and determine the system idle time. For example :


LASTINPUTINFO lii;
lii.cbSize = sizeof(LASTINPUTINFO);

GetSystemInputInfo(&lii);
DWORD currentTime = GetTickCount();

DWORD timeElapsed = currentTime - lii.dwTime;

This will give us, in milliseconds, the time for which the system has been idle. It can easily be converted to seconds, minutes, hours etc according to our needs.

There are two drawback of this function. Firstly, we cannot accurately measure the time beyond 49 days. This is in fact a limitation of the tick concept and the precision being DWORD (refer to the GetTickCount msdn article for furthur explaination). This ofcourse is not going to be a big concern for my app, as the use case of someone leaving the sysem idle for 49 days is very rare (I am targeting work stations and not servers).  The other drawback is that the GetSystemInputInfo returns the last input time for current user. This again is not a concern for my application, but could be an issue for applications like screensavers, auto shutdown etc.

The other method for tracking the system idle time is setting system wide hooks to capture the WM_KEYBOARD and WM_MOUSE events from the all processes, and keeping a count ourselves. I will discuss this method in another post as it is a bit more complicated.

I hope everyone finds this useful, and would love to hear some comments.

About these ads