Базы данныхИнтернетКомпьютерыОперационные системыПрограммированиеСетиСвязьРазное
Поиск по сайту:
Подпишись на рассылку:

Назад в раздел

Как долго простаивает операционная система.

div.main {margin-left: 20pt; margin-right: 20pt} Как долго простаивает операционная система.

Автор: Paul DiLascia

Скачать исходник к статье - 21 Кб (Компилятор: Visual C++ 6.0)

Вы задавались когда-нибудь вопросом, как можно определить сколько времени бездействует операционная система ? Или, например, как аська определяет, что пользователя нет за компьютером ? Проще говоря, как определить, сколько времени не трогали мышку или не стучали по клавиатуре ?

В Windows 2000 для этих целей предусмотрена системная функция GetLastInputInfo, которая заполняет структуру LASTINPUTINFO нужной нам информацией:

LASTINPUTINFO lpi; lpi.cbSize = sizeof(lpi); GetLastInputInfo(&lpi);

После вызова GetLastInputInfo, lpi.dwTime содержит количество миллисекунд, прошедших с момента прекращения каких либо действий пользователя. С одной стороны, это то, что нам нужно, но с другой - эта функция доступна только в Windows 2000 - но не в Windows 9x и не в Windows NT 4.0. Надо бы подумать, что в таком случае можно предпринять.

Наверное, проще всего будет написать свою версию GetLastInputInfo, а именно поставить глобальную ловушку (systemwide hook). Ловушка, это callback-функция, которую Windows вызывает каждый раз, когда случается что-нибудь интересное, например, когда пользователь что-нибудь напечатает на клавиатуре. Универсальной ловушки не существует, однако ловушкой на клавиатуру и ловушкой на мышь мы спокойно сможем перехватить весь пользовательский ввод. Единственное, что может раздражать в таком случае, это то, что ловушки должны жить в DLL.

Итак, для этой цели я написал простенькую DLL, которую назвал IdleUI и которая имеет всего три функции:

BOOL IdleUIInit() void IdleUITerm(); DWORD IdleUIGetLastInputTime();

Как Вы наверное уже догадались, IdleUIInit служит для инициализации, а IdleUITerm для завершения. Их можно спокойно вызывать из приложения MFC в функциях InitInstance и ExitInstance соответственно. Как только проинициализируется IdleUI, можно вызвать третью функцию IdleUIGetLastInputTime, чтобы получить количество тиков, прошедших с момента последнего пользовательского ввода, как это делает GetLastInputInfo.

Чтобы протестировать свою DLL, я написал программку TestIdleUI. Она вызывает IdleUIInit и IdleUITerm как описано выше и при этом отображает количество секунд бездействия клавиатуры и мышки.

void CMainFrame::OnPaint() { CPaintDC dc(this); CString s; DWORD nsec = (GetTickCount()- IdleUIGetLastInputTime())/1000; s.Format( "No mouse or keyboard input for %d seconds.",nsec); CRect rc; GetClientRect(&rc); dc.DrawText(s, &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE); }

Как это выглядит, можно посмотреть на рисунке 1. Для обеспечения непрерывности процесса отсчёта, в TestIdleUI используется односекундный таймер, который обновляет клиентскую область каждую секунду.

void CMainFrame::OnTimer(UINT) { Invalidate(); UpdateWindow(); }

Что может быть проще? Запускаем TestIdleUI и наблюдаем по секундам, как Ваш компьютер бездействует. Достаточно сдвинуть мышку и щёлкнуть по клавиатуре, как счётчик сбросится в ноль.


Рисунок 1 TestIdleUI

Как работает IdleUI? Когда Вы вызваете IdleUIInit, то она инсталлирует две ловушки: одну для мышки, а вторую для клавиатуры.

HHOOK g_hHookKbd; HHOOK g_hHookMouse; g_hHookKbd = SetWindowsHookEx(WH_KEYBOARD, MyKbdHook, hInst, 0); g_hHookMouse = SetWindowsHookEx(WH_MOUSE, MyMouseHook, hInst, 0);

Теперь если пользователь двигает мышку или нажимает клавишу на клавиатуре, Windows вызывает одну из этих ловушек и соответствующую ей функцию, которая записывает время:

LRESULT CALLBACK MyMouseHook(int code, WPARAM wp, LPARAM lp) { if (code==HC_ACTION) { // уведомляем счётчик тиков g_dwLastInputTick = GetTickCount(); } return ::CallNextHookEx(g_hHookMouse, code, wp, lp); }

Аналогичная операция делается для MyKbdHook. IdleUIGetLastInputTime возвращает g_dwLastInputTick, а IdleUITerm деинсталлирует обе ловушки.

Есть только одна тонкость. Обычно, когда Вы создаёте DLL, то компилятор помечает статические данные как нерасшаренные (nonshared), что означает, что каждый процесс, который вызывает DLL получает свою собственную копию данных - в данном случае g_hHookKbd, g_hHookMouse, и g_dwLastInputTick. Но нам-то нужен один и только один экземпляр этих данных. Поэтому необходимо сделать данные доступными. Для этого необходимо поместить их в специальный сегмент, который помен как доступный (shared). В коде это выглялит так:

#pragma data_seg (".IdleUI") // или любое другое имя HHOOK g_hHookKbd = NULL; HHOOK g_hHookMouse = NULL; DWORD g_dwLastInputTick = 0; #pragma data_seg ()

Этот код указывает компилятору, что три переменные необходимо поместить в сегмент данных с именем .IdleUI. Затем необходимо добавить следующую строчку в IdleUI.def, сделав тем самым сегмент расшаренным (доступным):

// в IdleUI.def SECTIONS .IdleUI READ WRITE SHARED

Вот собственно и всё. Удачи!



  • Главная
  • Новости
  • Новинки
  • Скрипты
  • Форум
  • Ссылки
  • О сайте




  • Emanual.ru – это сайт, посвящённый всем значимым событиям в IT-индустрии: новейшие разработки, уникальные методы и горячие новости! Тонны информации, полезной как для обычных пользователей, так и для самых продвинутых программистов! Интересные обсуждения на актуальные темы и огромная аудитория, которая может быть интересна широкому кругу рекламодателей. У нас вы узнаете всё о компьютерах, базах данных, операционных системах, сетях, инфраструктурах, связях и программированию на популярных языках!
     Copyright © 2001-2024
    Реклама на сайте