.NET — обнаружение движения мыши с помощью упрямого управления

Я пишу проект С#, который относительно прост. Подумайте об "общедоступном веб-терминале". По сути, это развернутая форма с прикрепленным к ней веб-браузером. Элемент управления веб-браузером, который я использую, — это элемент управления WebKit, найденный здесь:

Страница загрузки WebKit

Я пытаюсь определить время простоя системы, сохраняя DateTime, который представляет последний раз, когда было сделано движение мыши или нажатие клавиши.

Я установил обработчики событий (см. код ниже) и наткнулся на камень преткновения. События мыши (и клавиши), похоже, не срабатывают, когда моя мышь перемещается по веб-документу. Он работает нормально, когда моя мышь касается вертикальной полосы прокрутки элемента управления веб-браузером, поэтому я знаю, что код в порядке - кажется, это своего рода «оплошность» (из-за отсутствия лучшего слова) со стороны элемента управления.

Я думаю, мой вопрос: ко всем вам, программистам, как бы вы справились с этим?

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();
}

ОБНОВЛЕНИЕ

Используя принятое решение Джо, я собрал следующий класс. Спасибо всем, кто принимал участие.

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;
    }

ИСПОЛЬЗОВАНИЕ

idleTimeObject = new classIdleTime();
Int32 seconds = idleTimeObject.getIdleTime();
this.isIdle = (seconds > secondsBeforeIdle);

person Dutchie432    schedule 25.08.2010    source источник


Ответы (2)


Вы можете просто спросить Windows, не занят ли пользователь. Вам придется использовать P/Invoke, но это будет проще всего. Ознакомьтесь с функцией GetLastInputInfo.

person Joe    schedule 25.08.2010
comment
Реализовано и работает как мечта. Я добавил код для класса, который я собрал в исходном посте. - person Dutchie432; 26.08.2010

Это похоже на приложение WinForms — почему бы и нет добавить IMessageFilter? Вы сможете увидеть каждое сообщение Windows, проходящее через цикл обработки событий, независимо от того, нацелено оно на браузер или куда-то еще.

person Tim Robinson    schedule 25.08.2010
comment
Отличное предложение, но, поскольку это будет общедоступный терминал, ключевым фактором является производительность. На странице, на которую вы меня связали, было предупреждение о том, что добавление фильтров сообщений в насос сообщений для приложения может снизить производительность, поэтому я отказался от этого в долгосрочной перспективе. Голосуйте за отличный совет и усилия. - person Dutchie432; 26.08.2010
comment
@Dutchie432 Конечно, добавление любого кода в приложение может снизить производительность. Эффект от добавления фильтра сообщений и проверки сообщений мыши в нем такой же, как и при обработке событий мыши. Как всегда, прежде чем принять решение, измерьте профиль. - person Tim Robinson; 26.08.2010
comment
Помимо предостережения по вашей ссылке, принятое решение казалось проще, чем изобретать велосипед. Потребовалось всего несколько строк кода, и все было готово. Я бы обязательно попробовал ваше решение, если бы мне нужно было сделать что-то, что еще не было принято во внимание где-то еще. Спасибо еще раз. - person Dutchie432; 26.08.2010
comment
Я согласен, что GetLastInputInfo хорош, так как решает вашу проблему почти без кода. Я просто недоволен комментарием MSDN о производительности — он попахивает программированием карго-культа. - person Tim Robinson; 26.08.2010
comment
Я вижу вашу точку зрения. Я просто чувствую, что если есть предостережение, они, должно быть, сталкивались с проблемами с ним раньше и сказали, что вместо того, чтобы исправлять его или обучать разработчиков тому, как правильно его реализовать, и что приведет к деградации, мы просто выдадим предупреждение вверх. - person Dutchie432; 26.08.2010