Я написал некоторый код, который использует проверку таймера, когда был введен последний пользовательский ввод, и выводит его на консоль отладки Visual Studio.
#include <Windows.h>
#include <stdio.h>
DWORD InactiveThreshold; // The allowable amount of inactive time milliseconds
BOOL Inactive;
SYSTEMTIME CurrentTime(char *ddmmyyyy, char *hhmmss)
{
SYSTEMTIME lt;
GetLocalTime(<);
snprintf(ddmmyyyy, 11, "%d/%d/%d", lt.wDay, lt.wMonth, lt.wYear);
snprintf(hhmmss, 9, "%d:%d:%d", lt.wHour, lt.wMinute, lt.wSecond);
return lt;
}
void DebugOutput(char *ddmmyyyy, char *hhmmss)
{
OutputDebugString(TEXT("\n\n"));
OutputDebugString(ddmmyyyy);
OutputDebugString(TEXT(" -- "));
OutputDebugString(hhmmss);
OutputDebugString(TEXT(" : "));
OutputDebugString(TEXT("Inactive"));
}
void CALLBACK TimerProc(HWND hwnd, UINT unt, UINT_PTR id, DWORD current_time)
{
LASTINPUTINFO li;
SYSTEMTIME lt;
DWORD TimeSinceInput, RemainingTime;
char ddmmyyyy[11], hhmmss[9];
// Timers continue to expire, so we need to stop it first.
KillTimer(NULL, id);
li.cbSize = sizeof(LASTINPUTINFO);
GetLastInputInfo(&li);
TimeSinceInput = current_time - li.dwTime;
if (TimeSinceInput > InactiveThreshold)
{
// [Also find a way to check if audio or video was playing during the user inactive period]
if (!(Inactive))
{
// Set flag so it only outputs that it is inactive once during an inactive period
Inactive = TRUE;
lt = CurrentTime(ddmmyyyy, hhmmss);
// [Find way to print the start of the inactive period as timestamp,
// subtracting InactiveThreshold from current time]
DebugOutput(ddmmyyyy, hhmmss);
}
// [Change below so once Inactive, stop timer and instead set event loop
// to check for user input(keyboard / mouse) to end the inactive period
// and output timestamp of the end of the inactive period]
SetTimer(NULL, 0, InactiveThreshold, &TimerProc);
}
else
{
Inactive = FALSE;
RemainingTime = InactiveThreshold - TimeSinceInput;
SetTimer(NULL, 0, RemainingTime, &TimerProc);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
Inactive = FALSE;
InactiveThreshold = 30000; // 30 seconds
SetTimer(NULL, 0, InactiveThreshold, &TimerProc);
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
DispatchMessage(&msg);
}
return 0;
}
В идеале он должен печататься при отметке времени начала из неактивного периода было, затем, когда пользователь снова активен, чтобы напечатать отметку времени, когда неактивный период закончился. Однако есть три основные проблемы (также указанные в коде с комментариями в квадратных скобках // []):
- GetLastInputInfo () не учитывает, воспроизводит ли пользователь медиа (например, просматривает видео или прослушивание аудио в Google Chrome)
- При определении того, что система неактивна, как вычесть время InactiveThreshold в мс из текущей отметки времени, чтобы определить начало неактивного периода в качестве используемых типов данных отличаются
- Как вы могли бы установить обратный вызов события, чтобы снова ждать ввода пользовательской мыши / клавиатуры после того, как будет решено, что пользователь неактивен?