views:

58

answers:

2

I am writing a C# Project that is relatively simple. Think "Public Web Terminal". Essentially there is a maximized form with a fill-docked web browser on it. The web browser control I am using is the WebKit Control found here:

WebKit Download Page

I am trying to detect system idle time by keeping a DateTime which represents the last time a mouse movement or key press was made.

I have instituted event handlers (see code below), and have come across a stumbling block. The mouse (and key) events seem to not fire when my mouse moves over the web document. It DOES work fine when my mouse touches the vertical scroll bar portion of the web browser control, so I know the code is OK - it seems to be some sort of "oversight" (for lack of a better word) on the control's part.

I guess my question is - to all of you coders out there, how would you go about handling this?

this.webKitBrowser1.KeyPress += new KeyPressEventHandler(handleKeyPress);
this.webKitBrowser1.MouseMove += new MouseEventHandler(handleAction);
this.webKitBrowser1.MouseClick += new MouseEventHandler(handleAction);
this.webKitBrowser1.MouseDown += new MouseEventHandler(handleAction);
this.webKitBrowser1.MouseUp += new MouseEventHandler(handleAction);
this.webKitBrowser1.MouseDoubleClick += new MouseEventHandler(handleAction);

void handleKeyPress(object sender, KeyPressEventArgs e)
{
    this.handleAction(sender, null);
}

void handleAction(object sender, MouseEventArgs e)
{
    this.lastAction = DateTime.Now;
    this.label4.Text = this.lastAction.ToLongTimeString();
}

UPDATE

Using Joe's accepted solution, I put together the following class. Thanks to all who participated.

class classIdleTime
{
    [DllImport("user32.dll")]
    static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

    internal struct LASTINPUTINFO
    {
        public Int32 cbSize;
        public Int32 dwTime;
    }

    public int getIdleTime()
    {
        int systemUptime = Environment.TickCount;
        int LastInputTicks = 0;
        int IdleTicks = 0;

        LASTINPUTINFO LastInputInfo = new LASTINPUTINFO();
        LastInputInfo.cbSize = (Int32)Marshal.SizeOf(LastInputInfo);
        LastInputInfo.dwTime = 0;

        if (GetLastInputInfo(ref LastInputInfo))
        {
            LastInputTicks = (int)LastInputInfo.dwTime;
            IdleTicks = systemUptime - LastInputTicks;
        }
        Int32 seconds = IdleTicks / 1000;
        return seconds;
    }

USAGE

idleTimeObject = new classIdleTime();
Int32 seconds = idleTimeObject.getIdleTime();
this.isIdle = (seconds > secondsBeforeIdle);
+2  A: 

This looks like a WinForms app -- why not add an IMessageFilter? You'll get to see every Windows message that passes through the event loop, whether it's targetted at the browser or elsewhere.

Tim Robinson
Great suggestion, but because this will be a public terminal, performance is key. On the page you linked me to, there was a caution stating "Adding message filters to the message pump for an application can degrade performance.", so I decided against it in the long run. Upvote for the great advice and effort.
Dutchie432
@Dutchie432 Surely adding any code to an application can degrade performance. The effect of adding a message filter, and checking for mouse messages there, is the same as handling mouse events. As always with performance considerations, take profile measurements before deciding.
Tim Robinson
Aside from the caution at your link, the accepted solution just seemed easier than reinventing the wheel. It only took a few lines of code and it was finished. I would absolutely try your solution if I needed to do something that wasn't already taken into consideration someplace else. Thanks again.
Dutchie432
I agree `GetLastInputInfo` is nice, as it solves your problem with almost no code. I'm just unhappy with MSDN's performance comment -- it smacks of cargo cult programming.
Tim Robinson
I see your point. I just feel that if the caution is there, they must have run into problems with it before and said "instead of fixing it, or educating developers on how to properly implement it, and what will cause the degradation, we'll just throw a warning up".
Dutchie432
+1  A: 

You could just ask Windows if the user is idle. You'll have to use P/Invoke, but it would be the easiest. Check out the GetLastInputInfo function.

Joe
Implemented and working like a dream. I added the code for the class I put together in the original post.
Dutchie432