193 lines
6.4 KiB
C++
193 lines
6.4 KiB
C++
// Application class implementation
|
|
#include "pch.h"
|
|
|
|
#include "Application.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#define WM_TRAYICON WM_USER // Tray icon window message
|
|
#define IDM_EXIT 1001 // "Exit" menu identifier
|
|
#define IDT_UPDATE 1 // Update timer identifier
|
|
#define WM_UPDATE WM_USER + 1 // Update window message
|
|
|
|
namespace watchfuleye {
|
|
Application::Application(const char* appName, const char* appVersion, unsigned int maximumMinutes)
|
|
: m_appName(appName)
|
|
, m_appVersion(appVersion)
|
|
, m_mainDlg(nullptr)
|
|
, m_maxMinutes(maximumMinutes)
|
|
, m_startTime()
|
|
{
|
|
std::cout << std::format("{} {}\n", m_appName, m_appVersion);
|
|
}
|
|
|
|
void Application::run() {
|
|
m_startTime = Clock::now();
|
|
|
|
// Create dialog
|
|
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
|
|
|
m_mainDlg = CreateDialogParam(nullptr, MAKEINTRESOURCE(IDD_DIALOGMAIN), nullptr, reinterpret_cast<DLGPROC>(mainDlgProc), reinterpret_cast<LPARAM>(this));
|
|
|
|
// Create tray icon
|
|
createTrayIcon();
|
|
|
|
ShowWindow(m_mainDlg, SW_SHOW);
|
|
|
|
MSG msg = {};
|
|
while (GetMessage(&msg, nullptr, 0, 0))
|
|
IsDialogMessage(m_mainDlg, &msg);
|
|
}
|
|
|
|
BOOL CALLBACK Application::mainDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
|
static Application* app = nullptr;
|
|
static UINT taskbarCreatedMessage = 0;
|
|
static HBRUSH backgroundBrush = CreateSolidBrush(RGB(255, 150, 150));
|
|
static HFONT timeFont = nullptr;
|
|
|
|
switch (msg) {
|
|
case WM_INITDIALOG: {
|
|
app = reinterpret_cast<Application*>(lParam);
|
|
|
|
SetWindowText(dlg, app->m_appName.c_str());
|
|
SendMessage(dlg, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION))));
|
|
|
|
// Spawn in the lower right corner of the virtual screen (might be problematic in some cases)
|
|
int cornerX = GetSystemMetrics(SM_XVIRTUALSCREEN) + GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
|
int cornerY = GetSystemMetrics(SM_YVIRTUALSCREEN) + GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
|
SetWindowPos(dlg, nullptr, cornerX - 550, cornerY - 340, NULL, NULL, SWP_NOZORDER | SWP_NOSIZE);
|
|
|
|
taskbarCreatedMessage = RegisterWindowMessage("TaskbarCreated");
|
|
|
|
// Set up UI
|
|
LOGFONT lFont = {};
|
|
strcpy(lFont.lfFaceName, "Consolas");
|
|
lFont.lfHeight = 45;
|
|
HFONT upperFont = CreateFontIndirect(&lFont);
|
|
SendMessage(GetDlgItem(dlg, IDC_STATICUPPER), WM_SETFONT, reinterpret_cast<WPARAM>(upperFont), NULL);
|
|
|
|
lFont.lfHeight = 200;
|
|
lFont.lfWeight = FW_BOLD;
|
|
timeFont = CreateFontIndirect(&lFont);
|
|
|
|
SendMessage(dlg, WM_UPDATE, NULL, NULL);
|
|
SetTimer(dlg, IDT_UPDATE, 1000, nullptr);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_TRAYICON: {
|
|
if (LOWORD(lParam) == WM_RBUTTONDOWN) {
|
|
SetForegroundWindow(dlg);
|
|
|
|
POINT cursor = {};
|
|
GetCursorPos(&cursor);
|
|
|
|
HMENU popupMenu = CreatePopupMenu();
|
|
AppendMenu(popupMenu, MF_STRING, IDM_EXIT, "Exit");
|
|
|
|
TrackPopupMenu(popupMenu, NULL, cursor.x, cursor.y, NULL, dlg, nullptr); // Will block here. Might be problematic.
|
|
|
|
DestroyMenu(popupMenu);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_COMMAND: {
|
|
if (HIWORD(wParam) == 0 && LOWORD(wParam) == IDM_EXIT)
|
|
DestroyWindow(dlg);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_ERASEBKGND: {
|
|
HDC hDC = reinterpret_cast<HDC>(wParam);
|
|
|
|
RECT clientRect = {};
|
|
GetClientRect(dlg, &clientRect);
|
|
FillRect(hDC, &clientRect, backgroundBrush);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_CTLCOLORSTATIC: {
|
|
if (GetWindowLongPtr(reinterpret_cast<HWND>(lParam), GWL_EXSTYLE) & WS_EX_TRANSPARENT) {
|
|
SetBkMode(reinterpret_cast<HDC>(wParam), TRANSPARENT);
|
|
return reinterpret_cast<INT_PTR>(GetStockObject(NULL_BRUSH));
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
case WM_TIMER: {
|
|
if (wParam == IDT_UPDATE) {
|
|
SendMessage(dlg, WM_UPDATE, NULL, NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
case WM_UPDATE: {
|
|
InvalidateRect(dlg, nullptr, TRUE);
|
|
UpdateWindow(dlg);
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_PAINT: {
|
|
PAINTSTRUCT ps = {};
|
|
HDC hDC = BeginPaint(dlg, &ps);
|
|
|
|
RECT timeRect = {};
|
|
GetClientRect(dlg, &timeRect);
|
|
timeRect.top += 15, timeRect.bottom += 15;
|
|
SetTextColor(hDC, RGB(0, 0, 0));
|
|
SetBkMode(hDC, TRANSPARENT);
|
|
SelectObject(hDC, timeFont);
|
|
|
|
Seconds elapsed = Duration(Clock::now() - app->m_startTime).count();
|
|
Seconds remaining = app->m_maxMinutes * 60 - elapsed;
|
|
|
|
unsigned int minutes = remaining % (3600) / 60, seconds = remaining % 60;
|
|
|
|
DrawText(hDC, std::format("{:02}:{:02}", minutes, seconds).c_str(), -1, &timeRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
|
|
|
EndPaint(dlg, &ps);
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_CLOSE: {
|
|
// Do nothing
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_DESTROY: {
|
|
PostQuitMessage(0);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (msg == taskbarCreatedMessage)
|
|
app->createTrayIcon();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void Application::createTrayIcon() {
|
|
NOTIFYICONDATA iconData = {};
|
|
iconData.cbSize = sizeof(iconData);
|
|
iconData.uVersion = NOTIFYICON_VERSION_4;
|
|
iconData.hWnd = m_mainDlg;
|
|
iconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
|
|
iconData.uCallbackMessage = WM_TRAYICON;
|
|
iconData.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
|
|
strcpy(iconData.szTip, m_appName.c_str());
|
|
Shell_NotifyIcon(NIM_ADD, &iconData);
|
|
}
|
|
|
|
Application::~Application() {
|
|
|
|
}
|
|
}
|