Geoff Chappell - Software Analyst
Windows provides standard API functions for tracking the passing of time, with notifications issued on expiry of a timeout. However, this functionality measures time by the clock, without regard to whether the user was in any sense active. It is sometimes desirable that idle time, free of user input, should not count as time passed. SHELL32 provides just this facility, going by the name of User Event Timers, through an essentially undocumented COM class. Instances can be created using such well-documented COM functions as CoCreateInstance, by anyone who knows the CLSID:
CLSID_UserEventTimer | {864A1288-354C-4D19-9D68-C2742BB12997} |
The class implements the IUserEventTimer interface, with support from an IUserEventTimerCallback interface.
For each UserEventTimer object, SHELL32 creates a window with the class name “UserEventWindow”. Once created, this window exists only to handle messages. To receive such messages, the window sets at most one timer, in the sense of the standard Windows API function SetTimer. This timer is here called the internal timer. It is set to trigger periodically, making for a sequence of ticks. At each tick, the internal timer checks whether there was user input since the tick before. If there was not, then the interval between ticks is treated as idle time and is disregarded.
Through the IUserEventTimer interface, users of a UserEventTimer object set any number of user event timers, each with their own timeout period and their own directions for notification of the timeout’s expiry. The internal timer is set only while at least one user event timer is set. At each tick when the internal timer detects that there has been user input since the previous tick, the interval between ticks is counted against the time remaining for each user event timer. Where a deduction causes a user event timer to expire, that timer’s notification is triggered and its timeout is restored for counting down again.
The UserEventTimer class is implemented in SHELL32.DLL version 6.00 and higher.
Though the object and the related interfaces seem never to have been documented, they are declared in the SHOBJIDL.IDL (and thus also SHOBJIDL.H) from the Platform SDK dated February 2003. Those declarations may have been an oversight: they are removed from the Windows Vista SDK dated January 2007.