C # Как долго пользователь был неактивен - PullRequest
9 голосов
/ 14 сентября 2009

Некоторый фон: Я пишу приложение с несколькими формами и т. Д. Пользователи должны войти в систему, чтобы использовать большинство функций, и до сих пор это работало нормально. Однако теперь клиент запросил, чтобы пользователь вышел из системы после определенного количества неактивного времени. Проблема в том, что пользователь все еще может быть активным на компьютере, но не в моем приложении. Чтобы было ясно, я должен выйти из системы, когда он неактивен в моем приложении, даже если он все еще взаимодействует с рабочим столом.

Сначала я подумал, что это будет довольно просто. Просто запомните время последнего действия, постоянно сравнивайте его по таймеру с текущим временем и выйдите из системы, если прошедшее время превышает допустимое время. Однако я понял, что выяснить время последнего действия может быть не так просто ...

Конечно, я мог бы скопировать вставить что-то вроде

Program.LastActionTime = DateTime.Now;

в каждом событии OnChange, OnClick и т. Д. ... Однако не только то, что это будет большой объем работы из-за размера приложения ... Это также очень плохая практика, и я уверен, это будет забыто, по крайней мере, один раз, что сделает все это ненадежным (и, похоже, он сломан, ошибку почти невозможно воспроизвести!)

Итак, есть ли лучший способ?

Ответы [ 6 ]

6 голосов
/ 14 сентября 2009

Один из подходов, который я использовал в прошлом, создать MessageFilter в форме заявки и проверить наличие определенных типов событий, которые указывают на активность пользователя:

 public class UserActivityFilter : IMessageFilter
 {
        // Define WinAPI window message values (see pinvoke.net)
        private int WM_LBUTTONDOWN = 0x0201;
        private int WM_MBUTTONDOWN = 0x0207;
        private int WM_RBUTTONDOWN = 0x0204;
        private int WM_MOUSEWHEEL = 0x020A;
        private int WM_MOUSEMOVE = 0x0200;
        private int WM_KEYDOWN = 0x0100;

        public bool PreFilterMessage(ref Message m)
        {
            if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_MBUTTONDOWN || m.Msg == WM_RBUTTONDOWN || m.Msg == WM_MOUSEWHEEL || m.Msg == WM_MOUSEMOVE || m.Msg == WM_KEYDOWN)
            {
                //User activity has occurred
                // Reset a flag / timer etc.
            }
            return false;
        }
  }

Затем в методе Main () формы ДО вызова функции Run ():

Application.AddMessageFilter(new UserActivityFilter());

Одно предупреждение, добавление сложного фильтра сообщений или добавление нескольких отдельных фильтров может замедлить отзывчивость вашего приложения.

2 голосов
/ 14 сентября 2009

В вашем файле Program.CS вы можете обработать событие Application.Idle и сбросить там таймер. См:

http://msdn.microsoft.com/en-us/library/system.windows.forms.application.idle.aspx

1 голос
/ 14 сентября 2009

Вы можете переопределить WndProc, обновить Program.LastActionTime для каждого соответствующего Keyboard/Mouse сообщения о событии.

0 голосов
/ 14 сентября 2009

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

0 голосов
/ 14 сентября 2009

В целом, было бы лучше получить эту информацию из логики вашего приложения вместо необработанного пользовательского ввода, но я предполагаю, что у вас нет гибкой инфраструктуры (возможно, с использованием шаблона команды ), который мог бы обеспечить это информация.

Поэтому я предлагаю просто зарегистрировать обработчики в основной форме - если вы получаете щелчки или ключевые события (для этого включите Form.KeyPreview ), ваш пользователь активен, и вы можете сбросить время бездействия. 1007 *

0 голосов
/ 14 сентября 2009

Подключить обработчик событий к событиям MouseMove и KeyPressed, а затем проверить фокус внутри этого события?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...