-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMain.cpp
152 lines (121 loc) · 4.26 KB
/
Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <windows.h>
#include <cassert>
#include <iostream>
void PrintPowerStatus() {
SYSTEM_POWER_STATUS status = {};
BOOL ok = GetSystemPowerStatus(&status);
assert(ok); ok;
wprintf(L"Power status:\n");
if (status.ACLineStatus == 0) {
// DC case
wprintf(L" Running on battery power (DC).\n");
if (status.BatteryLifeTime != -1)
wprintf(L" Remaining battery time: %u min\n", status.BatteryLifeTime/60);
else
wprintf(L" Remaining battery time: <unknown>\n");
} else if (status.ACLineStatus == 1) {
// AC case
wprintf(L" Connected to AC power.\n");
if (status.BatteryFullLifeTime != -1)
wprintf(L" Time to full battery: %u min\n", status.BatteryFullLifeTime/60);
else
wprintf(L" Time to full battery: <unknown>\n");
} else {
// AC/DC unknown
}
if (status.BatteryLifePercent != 255)
wprintf(L" Battery charge: %u%%.\n", status.BatteryLifePercent);
else
wprintf(L" Battery charge: <unknown>\n");
wprintf(L"\n");
}
void TimerCallback(HWND, UINT, UINT_PTR, DWORD) {
PrintPowerStatus();
}
/** Process WM_POWERBROADCAST events. */
void ProcessPowerEvent(WPARAM wParam) {
wprintf(L"Power broadcast message:\n");
if (wParam == PBT_APMPOWERSTATUSCHANGE) {
wprintf(L" Power status change.\n");
PrintPowerStatus();
} else if (wParam == PBT_APMSUSPEND) {
wprintf(L" Suspending to low-power state.\n");
} else if (wParam == PBT_APMRESUMEAUTOMATIC) {
wprintf(L" Resuming from low-power state.\n");
// followed by PBT_APMRESUMESUSPEND _if_ triggered by user interaction
} else if (wParam == PBT_APMRESUMESUSPEND) {
// only delivered if resume is triggered by user interaction
wprintf(L" Resumed operation after being suspended.\n");
} else {
// other power event
wprintf(L" wParam=0x%x\n", (unsigned int)wParam);
}
}
/** Window procedure for processing messages. */
LRESULT CALLBACK WindowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_POWERBROADCAST:
ProcessPowerEvent(wParam);
break;
#if 0
case WM_DEVICECHANGE:
wprintf(L"HW attached or detached.\n");
break;
#endif
}
return DefWindowProc(wnd, msg, wParam, lParam);
}
/** Win32 timer RAII wrappers.
TODO: Figure out how to replace with std::unique_ptr or other standard RAII wrapper. */
class TimerWrap {
public:
TimerWrap(HWND wnd, UINT_PTR timer) : m_wnd(wnd), m_timer(timer) {
}
~TimerWrap() {
KillTimer(m_wnd, m_timer);
}
private:
HWND m_wnd = 0;
UINT_PTR m_timer = 0;
};
int WINAPI wmain () {
HINSTANCE instance = GetModuleHandleW(NULL);
// register window class
const wchar_t CLASS_NAME[] = L"PowerMonitor class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = instance;
wc.lpszClassName = CLASS_NAME;
RegisterClassW(&wc);
// create offscreen window
HWND wnd = CreateWindowExW(0, // optional window styles
CLASS_NAME, // window class
L"PowerMonitor", // window text
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, // size & position
NULL, // parent
NULL, // menu
instance, // instance handle
NULL // additional data
);
assert(wnd);
// don't call ShowWindow to keep the window hidden
// subscribe to PBT_APMSUSPEND, PBT_APMRESUMEAUTOMATIC & PBT_APMRESUMESUSPEND events
std::unique_ptr<std::remove_pointer<HPOWERNOTIFY>::type, BOOL(*)(HPOWERNOTIFY)> powNotify(RegisterSuspendResumeNotification(wnd, DEVICE_NOTIFY_WINDOW_HANDLE), UnregisterSuspendResumeNotification);
assert(powNotify);
// register for callback every 5sec
TimerWrap timer(wnd, SetTimer(wnd, 0, 5000, TimerCallback));
PrintPowerStatus();
// run message loop
MSG msg = {};
while (BOOL ret = GetMessageW(&msg, NULL, 0, 0) > 0) {
if (ret == -1) // error occured
break;
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}