C# Как долго пользователь был неактивен

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

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

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

Program.LastActionTime = DateTime.Now;

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

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

6 ответов

Решение

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

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

Один из подходов, который я использовал в прошлом, - создать 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());

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

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

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

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

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

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

Другие вопросы по тегам