1+ #include <windows.h>
2+ #include <commctrl.h>
3+ #include "tray.h"
4+ #include "timer.h"
5+ #include "power.h"
6+
7+ #define WM_TRAYICON (WM_USER + 1)
8+ #define APP_MUTEX_NAME "KeepAliveSingleInstance"
9+ #define FULLSCREEN_CHECK_TIMER 2
10+ #define FULLSCREEN_CHECK_INTERVAL 1000
11+
12+ HINSTANCE hInst ;
13+ HWND hwnd ;
14+ TrayContext trayCtx ;
15+ TimerContext timerCtx ;
16+ HANDLE hMutex ;
17+
18+ LRESULT CALLBACK WindowProc (HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam );
19+
20+ int WINAPI WinMain (HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdLine , int nCmdShow ) {
21+ hInst = hInstance ;
22+
23+ hMutex = CreateMutex (NULL , TRUE, APP_MUTEX_NAME );
24+ if (GetLastError () == ERROR_ALREADY_EXISTS ) {
25+ MessageBox (NULL , "KeepAlive is already running!" , "Warning" , MB_ICONWARNING );
26+ return 1 ;
27+ }
28+
29+ WNDCLASSEX wc = {0 };
30+ wc .cbSize = sizeof (WNDCLASSEX );
31+ wc .lpfnWndProc = WindowProc ;
32+ wc .hInstance = hInstance ;
33+ wc .lpszClassName = "KeepAliveClass" ;
34+ RegisterClassEx (& wc );
35+
36+ hwnd = CreateWindowEx (0 , "KeepAliveClass" , "KeepAlive" ,
37+ WS_OVERLAPPEDWINDOW , CW_USEDEFAULT , CW_USEDEFAULT ,
38+ 0 , 0 , NULL , NULL , hInstance , NULL );
39+
40+ trayCtx .hwnd = hwnd ;
41+ init_tray (& trayCtx , hInstance );
42+
43+ SetTimer (hwnd , FULLSCREEN_CHECK_TIMER , FULLSCREEN_CHECK_INTERVAL , NULL );
44+
45+ MSG msg ;
46+ while (GetMessage (& msg , NULL , 0 , 0 )) {
47+ TranslateMessage (& msg );
48+ DispatchMessage (& msg );
49+ }
50+
51+ cleanup_tray (& trayCtx );
52+ ReleaseMutex (hMutex );
53+ CloseHandle (hMutex );
54+ return 0 ;
55+ }
56+
57+ LRESULT CALLBACK WindowProc (HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam ) {
58+ switch (uMsg ) {
59+ case WM_TRAYICON :
60+ if (lParam == WM_RBUTTONUP ) {
61+ show_tray_menu (& trayCtx );
62+ }
63+ break ;
64+
65+ case WM_COMMAND :
66+ switch (LOWORD (wParam )) {
67+ case ID_START :
68+ start_timer (& timerCtx , hwnd , 30 );
69+ update_menu_state (& trayCtx , TRUE);
70+ break ;
71+ case ID_30MIN :
72+ start_timer (& timerCtx , hwnd , 30 );
73+ update_menu_state (& trayCtx , TRUE);
74+ break ;
75+ case ID_1HOUR :
76+ start_timer (& timerCtx , hwnd , 60 );
77+ update_menu_state (& trayCtx , TRUE);
78+ break ;
79+ case ID_2HOURS :
80+ start_timer (& timerCtx , hwnd , 120 );
81+ update_menu_state (& trayCtx , TRUE);
82+ break ;
83+ case ID_4HOURS :
84+ start_timer (& timerCtx , hwnd , 240 );
85+ update_menu_state (& trayCtx , TRUE);
86+ break ;
87+ case ID_8HOURS :
88+ start_timer (& timerCtx , hwnd , 480 );
89+ update_menu_state (& trayCtx , TRUE);
90+ break ;
91+ case ID_STOP :
92+ stop_timer (& timerCtx , hwnd );
93+ update_menu_state (& trayCtx , FALSE);
94+ break ;
95+ case ID_EXIT :
96+ PostQuitMessage (0 );
97+ break ;
98+ }
99+ update_tray_tip (& trayCtx , get_remaining_time_str (& timerCtx ));
100+ update_status_text (& trayCtx , get_remaining_time_str (& timerCtx ));
101+ break ;
102+
103+ case WM_TIMER :
104+ if (wParam == FULLSCREEN_CHECK_TIMER ) {
105+ check_fullscreen_state ();
106+ } else {
107+ update_timer_status (& timerCtx );
108+ if (!timerCtx .isActive ) {
109+ update_menu_state (& trayCtx , FALSE);
110+ }
111+ update_tray_tip (& trayCtx , get_remaining_time_str (& timerCtx ));
112+ update_status_text (& trayCtx , get_remaining_time_str (& timerCtx ));
113+ }
114+ break ;
115+
116+ case WM_DESTROY :
117+ PostQuitMessage (0 );
118+ break ;
119+ }
120+ return DefWindowProc (hwnd , uMsg , wParam , lParam );
121+ }
0 commit comments