跳到主要内容

github/tai

公开

Tai · Windows 软件与网站使用时长统计。上游 Planshit/Tai 的源码镜像,非灵栈原创;MIT 许可。来源:https://github.com/Planshit/Tai 。本次为手动同步,暂不提供安装包。

浏览文件

AppObserver.cs

117 行 · 3.9 KB历史下载
1using Core.Event;
2using Core.Librarys;
3using Core.Models.AppObserver;
4using Core.Servicers.Interfaces;
5using System;
6using System.Collections.Generic;
7using System.Diagnostics;
8using System.IO;
9using System.Linq;
10using System.Runtime.InteropServices;
11using System.Text;
12using System.Threading;
13using System.Threading.Tasks;
14using System.Timers;
15
16namespace Core.Servicers.Instances
17{
18 public class AppObserver : IAppObserver
19 {
20 public event AppObserverEventHandler OnAppActiveChanged;
21
22 #region win32 api
23 public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
24 IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
25 [DllImport("user32.dll")]
26 public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
27 hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
28 uint idThread, uint dwFlags);
29 [DllImport("user32.dll")]
30 public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
31 #endregion
32
33 // 获得焦点事件
34 private WinEventDelegate _foregroundEventDelegate;
35 private readonly IAppManager _appManager;
36 private readonly IWindowManager _windowManager;
37 private IntPtr _hook;
38 private bool _isStart = false;
39 private System.Timers.Timer _delayDetectTimer;
40 public AppObserver(IAppManager appManager_, IWindowManager windowManager)
41 {
42 _appManager = appManager_;
43 _windowManager = windowManager;
44 _foregroundEventDelegate = new WinEventDelegate(ForegroundEventCallback);
45 _delayDetectTimer = new System.Timers.Timer();
46 _delayDetectTimer.Interval = 1000;
47 _delayDetectTimer.Elapsed += DelayDetectTimer_Elapsed;
48 }
49
50
51
52 private void ForegroundEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
53 {
54 _delayDetectTimer?.Stop();
55 DateTime activeTime = DateTime.Now;
56 var stopwatch = Stopwatch.StartNew();
57 var args = GetAppInfoEventArgs(hwnd, activeTime);
58 Debug.WriteLine(activeTime);
59 Debug.WriteLine(args.App.ToString());
60 // 响应事件
61 OnAppActiveChanged?.Invoke(this, args);
62 if (args.App.Type == Enums.AppType.SystemComponent)
63 {
64 _delayDetectTimer?.Start();
65 }
66
67 }
68
69 private void DelayDetectTimer_Elapsed(object sender, ElapsedEventArgs e)
70 {
71 _delayDetectTimer?.Stop();
72 DelayDetect();
73 }
74
75 private void DelayDetect()
76 {
77 DateTime activeTime = DateTime.Now;
78 IntPtr w = Win32API.GetForegroundWindow();
79 var args = GetAppInfoEventArgs(w, activeTime);
80 if (args.App.Type != Enums.AppType.SystemComponent)
81 {
82 // 响应事件
83 OnAppActiveChanged?.Invoke(this, args);
84 }
85 }
86
87 private AppActiveChangedEventArgs GetAppInfoEventArgs(IntPtr handle_, DateTime activeTime_)
88 {
89 var app = _appManager.GetAppInfo(handle_);
90 var window = _windowManager.GetWindowInfo(handle_);
91 return new AppActiveChangedEventArgs(app, window, activeTime_);
92 }
93
94 private void HandleForegroundWindow()
95 {
96 IntPtr w = Win32API.GetForegroundWindow();
97 ForegroundEventCallback(IntPtr.Zero, 0, w, 0, 0, 0, 0);
98 }
99
100 public void Start()
101 {
102 if (_isStart)
103 {
104 return;
105 }
106 _isStart = true;
107 _hook = SetWinEventHook(0x0003, 0x0003, IntPtr.Zero, _foregroundEventDelegate, 0, 0, 0);
108 HandleForegroundWindow();
109 }
110
111 public void Stop()
112 {
113 _isStart = false;
114 UnhookWinEvent(_hook);
115 }
116 }
117}