最近发现DeskTime是一个不错的app,可以帮助监控自己的时间去哪里了,以及效率值,碎片化等等,有兴趣可以去点点
A Time Tracker App For Businesses & Freelancers | DeskTime
但是这东西需要付费,也没啥技术含量呀。
于是想着用C#写一个
这里就先讲讲思路
主要的功能拆分
- 监控前置窗口
- 监控idle,比如窗口前置,但人走开一段时间了,肯定不能算
- 图表绘制
先看怎么获取前置窗口
private static string GetActiveWindowTitle()
{
// 获取当前活动窗口的标题
IntPtr hWnd = GetForegroundWindow();
StringBuilder titleBuilder = new StringBuilder(256);
GetWindowText(hWnd, titleBuilder, titleBuilder.Capacity);
return titleBuilder.ToString();
}
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
运行就可以获得前置窗口的标题了,比如
Title '写文章-CSDN创作中心 - Google Chrome'
但是像一些进程会修改title,从而造成无法识别是啥东西,我们需要同时判断一下进程id,就比较稳了,方法如下
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
public static string GetProcessName(IntPtr foregroundWindowHandle)
{
try
{
uint processId;
GetWindowThreadProcessId(foregroundWindowHandle, out processId);
// 通过进程ID获取进程信息
Process process = Process.GetProcessById((int)processId);
return process.ProcessName;
}
catch
{
}
return "unknown";
}
优化后的结果如下
Title '新加卷 (F:)' process=explorer
然后是如何获取idle时间
[DllImport("user32.dll", SetLastError = true)]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
[StructLayout(LayoutKind.Sequential)]
struct LASTINPUTINFO
{
public uint cbSize;
public int dwTime;
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint GetTickCount();
private static uint GetLastInputTime()
{
LASTINPUTINFO lii = new LASTINPUTINFO();
lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
if (GetLastInputInfo(ref lii))
{
// dwTime is the tick count when the last input event was received
uint lastInputTick = (uint)Environment.TickCount - (uint)lii.dwTime;
return lastInputTick;
}
else
{
// Error handling
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
}
通过GetLastInputTime可以获取上次操作(鼠标键盘事件)到当前的时间ms数。
我们就可以很容易通过差值计算出非活跃时间了
分类
现在我们通过采集,可以获得主窗口标题和进程名两个信息,然后要做的就是做标题聚合
其实就是吧两个属性合并成一个最后分类使用的string
private static string Convert(string title, string processName)
{
if (processName.Contains("chrome"))
{
else if (title.Contains("csdn"))
return "csdn";
else if (title.Contains("百度"))
return "百度";
else if (title.Contains("bilibili"))
return "bilibili";
else if (title.Contains("lockapp"))
return "idle";
return title;
}
else
{
if (title.Contains("microsoft visual studio"))
return "vss";
else if (title.Contains("visual studio code"))
return "vscode";
else if (title.Contains("记事本"))
return "记事本";
return processName;
}
}
图表绘制
搞个插件画一下,应该不成问题
最后的效果如图,和desktime差别不大吧