Иногда приложениям требуется узнать время бездействия системы, то есть интервал времени, прошедший с момента когда пользователь последний раз пошевелил мышкой или нажал какую-нибудь кнопку на клавиатуре. Для определения время бездействия системы в системах Windows 2000 и старше используется функция API
GetLastInputInfo. Она возвращает количество миллисекунд (тиков таймера), прошедшее от старта системы до момента последнего ввода. Время бездействия вычисляется как арифметическая разница между данными, возвращаемыми функцией
GetTickCount и данными из GetLastInputInfo. В FASM, как обычно, ничего из нужных структур не определено, лезем в
MSDN:
section '.data' data readable writeable
struct LASTINPUTINFO
cbSize dd ? ; Размер структуры
dwTime dd ? ; Время бездействия
ends
lii LASTINPUTINFO
Получение времени бездействия системы:
Code (Assembler) : Убрать нумерацию
...
; Получить время последнего ввода
mov [lii.cbSize],sizeof.LASTINPUTINFO
invoke GetLastInputInfo,lii
; Получить текущее время в миллисекундах
invoke GetTickCount
; EAX - время бездействия системы в миллисекундах
sub eax,[lii.dwTime]
...
Это был самый простой способ, работающий на всех новых системах. В старых операционках типа Windows 9x функция GetLastInputInfo отсутствует, поэтому там придется использовать другой, более громоздкий способ с применением глобальных системных хуков.
Чтобы перехват получился глобальным, придется загружать в память DLL с нужными функциями и устанавливать хуки уже на нее. Хуки будем ставить двух типов: через WH_MOUSE на мышь и через WH_KEYBOARD на клавиатуру. При наступлении любого из этих событий в переменную, находящуюся в shared-памяти DLL, будет записываться значение из функции GetTickCount, а при вызове какой-нибудь заранее определенной функции, это значение будет передаваться нашему приложению. Полный текст DLL я тут приводить не буду, можете посмотреть его, скачав прилагаемый файл с исходниками. В основное приложение DLL подгружается через импорт, при инициализации DLL ставятся глобальные хуки, а при выходе из приложения хуки должны обязательно сниматься.
...
; Получить время последнего ввода
invoke GetLastInputTime
mov ebx,eax
; Получить текущее время в миллисекундах
invoke GetTickCount
; EAX - время бездействия системы в миллисекундах
sub eax,ebx
...
...
...
.wmclose:
; Снять глобальные хуки
invoke UnloadDll
...
Этот метод универсальный и работает на всех системах. Но приходится таскать за собой дополнительную DLL, к установке глобальных хуков некоторые "как-бы-антивирусы" и мониторы могут отнестись с подозрением, ну и вдобавок получается много лишнего кода. Выбор оставляю за вами.
В приложении две программы, реализующие оба описанных выше метода. В диалоговом окне они показывают счетчик секунд, прошедших с момента последней активности пользователя. Чтобы сбросить счетчик пошевелите мышкой или нажмите любую клавишу.