From 8d070ca5f4006a427b0cfd207958f001255992e3 Mon Sep 17 00:00:00 2001 From: Grayson Riffe Date: Thu, 4 Jun 2026 22:39:08 -0500 Subject: [PATCH] Add countdown and fix flicker --- WatchfulEye/resource.rc | 7 ++-- WatchfulEye/src/Application.cpp | 65 +++++++++++++++++++++++++++------ WatchfulEye/src/Application.h | 10 ++++- WatchfulEye/src/main.cpp | 2 +- WatchfulEye/src/resource.h | 3 +- 5 files changed, 67 insertions(+), 20 deletions(-) diff --git a/WatchfulEye/resource.rc b/WatchfulEye/resource.rc index c6eb1f4..96ec08b 100644 --- a/WatchfulEye/resource.rc +++ b/WatchfulEye/resource.rc @@ -49,13 +49,12 @@ END // IDD_DIALOGMAIN DIALOGEX 0, 0, 300, 114 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CAPTION | WS_SYSMENU -EXSTYLE WS_EX_TOPMOST +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CAPTION +EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW CAPTION "Dialog" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - CTEXT "00:00",IDC_STATICTIME,17,35,266,60,SS_CENTERIMAGE,WS_EX_TRANSPARENT - CTEXT "Time left on tester:",IDC_STATICUPPER,7,4,286,22,SS_CENTERIMAGE,WS_EX_TRANSPARENT + CTEXT "Time Remaining on Tester",IDC_STATICUPPER,7,4,286,22,SS_CENTERIMAGE,WS_EX_TRANSPARENT END diff --git a/WatchfulEye/src/Application.cpp b/WatchfulEye/src/Application.cpp index 971e338..6ffca50 100644 --- a/WatchfulEye/src/Application.cpp +++ b/WatchfulEye/src/Application.cpp @@ -5,19 +5,25 @@ #include "resource.h" -#define WM_TRAYICON WM_USER -#define IDM_EXIT 1001 +#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) + 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); @@ -36,6 +42,8 @@ namespace watchfuleye { 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: { @@ -54,14 +62,16 @@ namespace watchfuleye { // Set up UI LOGFONT lFont = {}; strcpy(lFont.lfFaceName, "Consolas"); - lFont.lfHeight = 50; + lFont.lfHeight = 45; HFONT upperFont = CreateFontIndirect(&lFont); SendMessage(GetDlgItem(dlg, IDC_STATICUPPER), WM_SETFONT, reinterpret_cast(upperFont), NULL); lFont.lfHeight = 200; - HFONT timeFont = CreateFontIndirect(&lFont); - SendMessage(GetDlgItem(dlg, IDC_STATICTIME), WM_SETFONT, reinterpret_cast(timeFont), NULL); + lFont.lfWeight = FW_BOLD; + timeFont = CreateFontIndirect(&lFont); + SendMessage(dlg, WM_UPDATE, NULL, NULL); + SetTimer(dlg, IDT_UPDATE, 1000, nullptr); return TRUE; } @@ -94,28 +104,59 @@ namespace watchfuleye { case WM_ERASEBKGND: { HDC hDC = reinterpret_cast(wParam); - HBRUSH backgroundBrush = CreateSolidBrush(RGB(255, 150, 150)); - RECT clientRect = {}; GetClientRect(dlg, &clientRect); FillRect(hDC, &clientRect, backgroundBrush); - DeleteObject(backgroundBrush); - return TRUE; } case WM_CTLCOLORSTATIC: { if (GetWindowLongPtr(reinterpret_cast(lParam), GWL_EXSTYLE) & WS_EX_TRANSPARENT) { - std::cout << "Test\n"; SetBkMode(reinterpret_cast(wParam), TRANSPARENT); - return reinterpret_cast(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; diff --git a/WatchfulEye/src/Application.h b/WatchfulEye/src/Application.h index 0ad8aa7..d06df94 100644 --- a/WatchfulEye/src/Application.h +++ b/WatchfulEye/src/Application.h @@ -2,8 +2,13 @@ namespace watchfuleye { class Application { + using Clock = std::chrono::high_resolution_clock; + using TimePoint = std::chrono::time_point; + using Duration = std::chrono::duration>; + using Seconds = int; + public: - Application(const char* appName, const char* appVersion); + Application(const char* appName, const char* appVersion, unsigned int maximumMinutes); void run(); @@ -15,5 +20,8 @@ namespace watchfuleye { std::string m_appName, m_appVersion; HWND m_mainDlg; + + unsigned int m_maxMinutes; + TimePoint m_startTime; }; } diff --git a/WatchfulEye/src/main.cpp b/WatchfulEye/src/main.cpp index 83c44bb..694d756 100644 --- a/WatchfulEye/src/main.cpp +++ b/WatchfulEye/src/main.cpp @@ -13,7 +13,7 @@ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") int main(int argc, char* argv[]) { { - watchfuleye::Application app(APPNAME, APPVERSION); + watchfuleye::Application app(APPNAME, APPVERSION, 15); app.run(); } diff --git a/WatchfulEye/src/resource.h b/WatchfulEye/src/resource.h index aef7753..246a80c 100644 --- a/WatchfulEye/src/resource.h +++ b/WatchfulEye/src/resource.h @@ -3,8 +3,7 @@ // Used by C:\Users\Grayson\Documents\Visual Studio 18\Solutions\watchful-eye\WatchfulEye\resource.rc // #define IDD_DIALOGMAIN 101 -#define IDC_STATICTIME 1000 -#define IDC_STATICUPPER 1001 +#define IDC_STATICUPPER 1000 // Next default values for new objects //