4 #include <WinSock2.h>
\r
8 #define LAY_IMPLEMENTATION
\r
12 #include <stdbool.h>
\r
15 #include <windows.h>
\r
16 #include <shlwapi.h>
\r
18 bool recording = false;
\r
19 HANDLE process = NULL;
\r
21 HINSTANCE hInstance;
\r
24 NOTIFYICONDATAA niData = { 0 };
\r
25 const UINT ICON_MSG = WM_APP+1;
\r
27 ShowNotificationIcon()
\r
29 Shell_NotifyIconA(NIM_ADD, &niData);
\r
30 Shell_NotifyIconA(NIM_SETVERSION, &niData);
\r
34 HideNotificationIcon()
\r
36 Shell_NotifyIconA(NIM_DELETE, &niData);
\r
39 void changeIcon(HWND hwnd, HINSTANCE hInstance, WORD id)
\r
41 HICON icon = LoadIcon(hInstance, MAKEINTRESOURCE(id));
\r
42 niData.hIcon = icon;
\r
43 if (! IsWindowVisible(hwnd))
\r
44 Shell_NotifyIconA(NIM_MODIFY, &niData);
\r
45 SendMessage(hwnd, WM_SETICON, 0, (LPARAM)icon);
\r
46 SendMessage(hwnd, WM_SETICON, 1, (LPARAM)icon);
\r
54 ws::sendRequest("StartRecord");
\r
55 changeIcon(hwnd, hInstance, IDI_ICON_GREEN);
\r
61 ws::sendRequest("StopRecord");
\r
62 changeIcon(hwnd, hInstance, IDI_ICON_RED);
\r
66 checkProcessRunning(HANDLE handle)
\r
70 if (handle != NULL && GetExitCodeProcess(handle, &exit_code)) {
\r
71 return exit_code == STILL_ACTIVE;
\r
78 getHwndProcess(HWND hwnd)
\r
80 DWORD processId, threadId = GetWindowThreadProcessId(hwnd, &processId);
\r
81 return OpenProcess(PROCESS_QUERY_INFORMATION, false, processId);
\r
84 // HWND getProcessHwnd(HANDLE handle) {}
\r
87 checkFullscreenWindow()
\r
89 HWND desktopHwnd = GetDesktopWindow();
\r
90 HWND fgHwnd = GetForegroundWindow();
\r
92 if (fgHwnd != desktopHwnd && fgHwnd != GetShellWindow()) {
\r
93 RECT windowRect, desktopRect;
\r
94 // Get Window and Desktop size
\r
95 GetWindowRect(fgHwnd, &windowRect);
\r
96 GetWindowRect(desktopHwnd, &desktopRect);
\r
98 bool fullscreen = windowRect.bottom == desktopRect.bottom &&
\r
99 windowRect.top == desktopRect.top &&
\r
100 windowRect.left == desktopRect.left &&
\r
101 windowRect.right == desktopRect.right;
\r
110 checkForegroundProcess(std::string exeName)
\r
112 HWND fgHwnd = GetForegroundWindow();
\r
113 HANDLE fgHandle = getHwndProcess(fgHwnd);
\r
115 char filename[1024];
\r
116 int len = GetModuleFileNameExA(fgHandle, NULL, filename, 1024);
\r
117 PathStripPathA(filename);
\r
119 return strcmp(filename, exeName.c_str()) == 0;
\r
123 WinMain(HINSTANCE hInstance,
\r
124 HINSTANCE hPrevInstance,
\r
127 //int main(int argc, char **argv)
\r
129 hInstance = GetModuleHandle(0);
\r
131 win::Window window("Title", "MyWindowClass", hInstance);
\r
132 hwnd = window.hwnd;
\r
134 niData.cbSize = sizeof(niData);
\r
135 niData.uID = 12345;
\r
136 niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
\r
137 niData.hIcon = LoadIconA(hInstance, MAKEINTRESOURCEA(IDI_ICON_WHITE));
\r
138 niData.hWnd = window.hwnd;
\r
139 niData.uCallbackMessage = ICON_MSG;
\r
140 niData.uVersion = NOTIFYICON_VERSION_4;
\r
142 window.handlers[WM_SIZE].push_back([](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
\r
143 if (wParam == SIZE_MINIMIZED) {
\r
144 ShowNotificationIcon();
\r
145 ShowWindow(hwnd, false);
\r
148 window.handlers[WM_DESTROY].push_back([](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
\r
149 HideNotificationIcon();
\r
151 window.handlers[ICON_MSG].push_back([](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
\r
152 if (LOWORD(lParam) == NIN_SELECT) {
\r
153 HideNotificationIcon();
\r
154 ShowWindow(hwnd, true);
\r
155 SetForegroundWindow(hwnd);
\r
156 SetActiveWindow(hwnd);
\r
160 window.handlers[WM_GETMINMAXINFO].push_back([](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
\r
161 MINMAXINFO *mmInfo = (MINMAXINFO*)lParam;
\r
162 mmInfo->ptMinTrackSize.x = 400;
\r
163 mmInfo->ptMinTrackSize.y = 200;
\r
166 lay_context *ctx = &window.ctx;
\r
167 lay_id root = window.lId;
\r
169 lay_id row1 = win::createLayId(&window.ctx, window.lId, 0, 25, LAY_ROW, LAY_LEFT);
\r
170 lay_set_margins_ltrb(ctx, row1, 5, 5, 5, 5);
\r
171 lay_id row2 = win::createLayId(&window.ctx, window.lId, 0, 0, LAY_ROW, LAY_FILL);
\r
172 lay_set_margins_ltrb(ctx, row2, 5, 5, 5, 5);
\r
174 win::CheckBox cbWindowTitle(&window, "Window Title", row1, 100, 25, 0, 0);
\r
175 win::CheckBox cbFullscreenWindow(&window, "Any Fullscreen Application", row1, 200, 25, 0, 0);
\r
177 win::Button btnConnect(&window, "Connect", row1, 100, 25, 0, 0);
\r
178 btnConnect.onClick([&]() {
\r
179 ws::connect("ws://127.0.0.1:4444");
\r
181 win::Button btnTest(&window, "Test", row1, 100, 25, 0, 0);
\r
182 btnTest.onClick([&]() {
\r
183 changeIcon(window.hwnd, hInstance, IDI_ICON_GREEN);
\r
186 win::ListBox lstActiveProcesses(&window, row2, 0, 0, 0, LAY_FILL);
\r
188 lay_id col1 = win::createLayId(&window.ctx, row2, 80, 0, LAY_COLUMN, LAY_VCENTER);
\r
189 lstActiveProcesses.addStyle(WS_VSCROLL);
\r
191 lay_set_margins_ltrb(ctx, col1, 5, 0, 5, 0);
\r
193 win::ListBox lstMonitoredProcesses(&window, row2, 0, 0, 0, LAY_FILL);
\r
194 lstMonitoredProcesses.addStyle(WS_VSCROLL);
\r
196 win::Button btnUpdateWindows(&window, "Update", col1, 85, 25, 0, 0);
\r
197 win::Button btnStartMonitoringName(&window, "Exe name >>", col1, 85, 25, 0, 0);
\r
198 win::Button btnStartMonitoringPath(&window, "Full path >>", col1, 85, 25, 0, 0);
\r
199 win::Button btnStopMonitoring(&window, "Remove", col1, 85, 25, 0, 0);
\r
200 btnUpdateWindows.onClick([&]() {
\r
201 lstActiveProcesses.clear();
\r
202 for (HWND hwnd = GetTopWindow(NULL); hwnd != nullptr;
\r
203 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT)) {
\r
204 if (!IsWindowVisible(hwnd))
\r
208 GetWindowRect(hwnd, &rect);
\r
211 if (GetModuleFileNameExA(getHwndProcess(hwnd), 0, str, 1024) != 0 &&
\r
212 lstActiveProcesses.findString(str) == LB_ERR) {
\r
213 lstActiveProcesses.addString(str);
\r
217 btnStartMonitoringName.onClick([&]() {
\r
218 int sel = lstActiveProcesses.getSelectedIndex();
\r
219 if (sel < 0) return;
\r
221 std::string selStr = lstActiveProcesses.getText(sel);
\r
223 char *filename = new char[selStr.size()];
\r
224 std::memcpy(filename, selStr.c_str(), selStr.size());
\r
225 PathStripPathA(filename);
\r
227 if (lstMonitoredProcesses.findString(std::string(filename)) == LB_ERR)
\r
228 lstMonitoredProcesses.addString(std::string(filename));
\r
232 btnStartMonitoringPath.onClick([&]() {
\r
233 int sel = lstActiveProcesses.getSelectedIndex();
\r
234 if (sel < 0) return;
\r
235 std::string selStr = lstActiveProcesses.getText(sel);
\r
236 if (lstMonitoredProcesses.findString(selStr) == LB_ERR)
\r
237 lstMonitoredProcesses.addString(selStr);
\r
239 btnStopMonitoring.onClick([&]() {
\r
240 int sel = lstMonitoredProcesses.getSelectedIndex();
\r
241 if (sel < 0) return;
\r
242 lstMonitoredProcesses.remove(sel);
\r
246 window.setDefaultFont();
\r
248 ws::onConnect = [&]() {
\r
249 changeIcon(window.hwnd, hInstance, IDI_ICON_RED);
\r
253 SetTimer(window.hwnd, 10123, 100, [](HWND, UINT, UINT_PTR, DWORD) {
\r
255 if (checkForegroundProcess("League of Legends.exe")) {
\r
257 process = getHwndProcess(GetForegroundWindow());
\r
261 if (!checkProcessRunning(process)) {
\r
269 while (window.update()) {
\r