C Windows API 确定用户是不是处于非活动状态,包括播放媒体
Posted
技术标签:
【中文标题】C Windows API 确定用户是不是处于非活动状态,包括播放媒体【英文标题】:C Windows API determine if user is inactive inclusive of playing mediaC Windows API 确定用户是否处于非活动状态,包括播放媒体 【发布时间】:2020-04-27 04:15:38 【问题描述】:我编写了一些代码,利用计时器检查最后一次用户输入的时间并将其打印到 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;
理想情况下,它应该打印非活动期开始的时间戳,然后当用户再次活动时打印非活动期结束的时间戳。但是存在三个主要问题(在代码中也用方括号 cmets //[] 表示):
GetLastInputInfo() 不会考虑用户是否正在播放媒体(例如:在 Google Chrome 中观看视频或收听音频) 当确定系统处于非活动状态时,如何从当前时间戳中减去以毫秒为单位的 InactiveThreshold 时间以确定非活动期的开始,因为使用的数据类型不同 一旦确定用户处于非活动状态,如何设置事件回调以再次等待用户鼠标/键盘输入?【问题讨论】:
我已从您的帖子中删除了 C++ 标签。您所写的内容与 C++ 没有任何关系。代码的标题和整个代码完全是 C。请不要使用与您的帖子不直接相关的标签来标记垃圾邮件。胡萝卜、汽车和猫不是一回事,因为它们都以 ca 开头。标签在这里有意义,所以请只使用那些实际适用的。谢谢。 @ken:这是一个随意的选择。出于同样的原因,问题中没有任何东西不能使它成为 C++。那么为什么要标记一个而不标记另一个。任何一个都同样适用。我正在还原您的更改。 @mic:可以通过多种方式请求当前时间。如果您需要与GetLastInputInfo
返回的值兼容的时间戳,则需要调用GetTickCount
。
"一旦确定用户处于非活动状态,如何设置事件回调以再次等待用户鼠标/键盘输入?" - 可以检测到新的用户活动使用SetWindowsHookEx()
或RegisterRawInputDevices()
【参考方案1】:
GetLastInputInfo() 不考虑用户是否在玩 媒体(例如:在 Google Chrome 中观看视频或收听音频)
据我了解,系统本身仅跟踪来自GetLastInputInfo()
的活动。
诸如“用户正在观看视频”之类的情况通过发送WM_SYSCOMMAND
和SC_SCREENSAVE
或SC_MONITORPOWER
来处理,因此如果应用程序吞下此类消息而不是传递给DefWindowProc
,屏幕不会变为空白。或者通过SetThreadExecutionState
和ES_DISPLAY_REQUIRED
背景音频等情况由SetThreadExecutionState
和ES_SYSTEM_REQUIRED
处理。
这一切都意味着确实发生了用户不活动,但其他一些情况会阻止对这种不活动采取行动。
恐怕应用程序无法可靠地检测到所有此类情况。
【讨论】:
以上是关于C Windows API 确定用户是不是处于非活动状态,包括播放媒体的主要内容,如果未能解决你的问题,请参考以下文章
windows中哪些API能了解用户是不是在使用鼠标或者键盘?
C/C++/Assembly 以编程方式检测超线程在 Windows、Mac 和 Linux 上是不是处于活动状态 [重复]