Add countdown and fix flicker

This commit is contained in:
Grayson Riffe 2026-06-04 22:39:08 -05:00
parent cf310dc71c
commit 8d070ca5f4
Signed by: grayson
SSH Key Fingerprint: SHA256:23HJg9tnL2m6u0uUb26QIrOTFymFZ+xgSH/2UPEBB/I
5 changed files with 67 additions and 20 deletions

View File

@ -49,13 +49,12 @@ END
// //
IDD_DIALOGMAIN DIALOGEX 0, 0, 300, 114 IDD_DIALOGMAIN DIALOGEX 0, 0, 300, 114
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_FIXEDSYS | WS_CAPTION
EXSTYLE WS_EX_TOPMOST EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW
CAPTION "Dialog" CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
CTEXT "00:00",IDC_STATICTIME,17,35,266,60,SS_CENTERIMAGE,WS_EX_TRANSPARENT CTEXT "Time Remaining on Tester",IDC_STATICUPPER,7,4,286,22,SS_CENTERIMAGE,WS_EX_TRANSPARENT
CTEXT "Time left on tester:",IDC_STATICUPPER,7,4,286,22,SS_CENTERIMAGE,WS_EX_TRANSPARENT
END END

View File

@ -5,19 +5,25 @@
#include "resource.h" #include "resource.h"
#define WM_TRAYICON WM_USER #define WM_TRAYICON WM_USER // Tray icon window message
#define IDM_EXIT 1001 #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 { 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_appName(appName)
, m_appVersion(appVersion) , m_appVersion(appVersion)
, m_mainDlg(nullptr) , m_mainDlg(nullptr)
, m_maxMinutes(maximumMinutes)
, m_startTime()
{ {
std::cout << std::format("{} {}\n", m_appName, m_appVersion); std::cout << std::format("{} {}\n", m_appName, m_appVersion);
} }
void Application::run() { void Application::run() {
m_startTime = Clock::now();
// Create dialog // Create dialog
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); 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) { BOOL CALLBACK Application::mainDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) {
static Application* app = nullptr; static Application* app = nullptr;
static UINT taskbarCreatedMessage = 0; static UINT taskbarCreatedMessage = 0;
static HBRUSH backgroundBrush = CreateSolidBrush(RGB(255, 150, 150));
static HFONT timeFont = nullptr;
switch (msg) { switch (msg) {
case WM_INITDIALOG: { case WM_INITDIALOG: {
@ -54,14 +62,16 @@ namespace watchfuleye {
// Set up UI // Set up UI
LOGFONT lFont = {}; LOGFONT lFont = {};
strcpy(lFont.lfFaceName, "Consolas"); strcpy(lFont.lfFaceName, "Consolas");
lFont.lfHeight = 50; lFont.lfHeight = 45;
HFONT upperFont = CreateFontIndirect(&lFont); HFONT upperFont = CreateFontIndirect(&lFont);
SendMessage(GetDlgItem(dlg, IDC_STATICUPPER), WM_SETFONT, reinterpret_cast<WPARAM>(upperFont), NULL); SendMessage(GetDlgItem(dlg, IDC_STATICUPPER), WM_SETFONT, reinterpret_cast<WPARAM>(upperFont), NULL);
lFont.lfHeight = 200; lFont.lfHeight = 200;
HFONT timeFont = CreateFontIndirect(&lFont); lFont.lfWeight = FW_BOLD;
SendMessage(GetDlgItem(dlg, IDC_STATICTIME), WM_SETFONT, reinterpret_cast<WPARAM>(timeFont), NULL); timeFont = CreateFontIndirect(&lFont);
SendMessage(dlg, WM_UPDATE, NULL, NULL);
SetTimer(dlg, IDT_UPDATE, 1000, nullptr);
return TRUE; return TRUE;
} }
@ -94,28 +104,59 @@ namespace watchfuleye {
case WM_ERASEBKGND: { case WM_ERASEBKGND: {
HDC hDC = reinterpret_cast<HDC>(wParam); HDC hDC = reinterpret_cast<HDC>(wParam);
HBRUSH backgroundBrush = CreateSolidBrush(RGB(255, 150, 150));
RECT clientRect = {}; RECT clientRect = {};
GetClientRect(dlg, &clientRect); GetClientRect(dlg, &clientRect);
FillRect(hDC, &clientRect, backgroundBrush); FillRect(hDC, &clientRect, backgroundBrush);
DeleteObject(backgroundBrush);
return TRUE; return TRUE;
} }
case WM_CTLCOLORSTATIC: { case WM_CTLCOLORSTATIC: {
if (GetWindowLongPtr(reinterpret_cast<HWND>(lParam), GWL_EXSTYLE) & WS_EX_TRANSPARENT) { if (GetWindowLongPtr(reinterpret_cast<HWND>(lParam), GWL_EXSTYLE) & WS_EX_TRANSPARENT) {
std::cout << "Test\n";
SetBkMode(reinterpret_cast<HDC>(wParam), TRANSPARENT); SetBkMode(reinterpret_cast<HDC>(wParam), TRANSPARENT);
return reinterpret_cast<INT_PTR>(GetStockObject(NULL_BRUSH)); return reinterpret_cast<INT_PTR>(GetStockObject(NULL_BRUSH));
} }
return FALSE; 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: { case WM_CLOSE: {
// Do nothing // Do nothing
return TRUE; return TRUE;

View File

@ -2,8 +2,13 @@
namespace watchfuleye { namespace watchfuleye {
class Application { class Application {
using Clock = std::chrono::high_resolution_clock;
using TimePoint = std::chrono::time_point<Clock>;
using Duration = std::chrono::duration<double, std::ratio<1, 1>>;
using Seconds = int;
public: public:
Application(const char* appName, const char* appVersion); Application(const char* appName, const char* appVersion, unsigned int maximumMinutes);
void run(); void run();
@ -15,5 +20,8 @@ namespace watchfuleye {
std::string m_appName, m_appVersion; std::string m_appName, m_appVersion;
HWND m_mainDlg; HWND m_mainDlg;
unsigned int m_maxMinutes;
TimePoint m_startTime;
}; };
} }

View File

@ -13,7 +13,7 @@ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
{ {
watchfuleye::Application app(APPNAME, APPVERSION); watchfuleye::Application app(APPNAME, APPVERSION, 15);
app.run(); app.run();
} }

View File

@ -3,8 +3,7 @@
// Used by C:\Users\Grayson\Documents\Visual Studio 18\Solutions\watchful-eye\WatchfulEye\resource.rc // Used by C:\Users\Grayson\Documents\Visual Studio 18\Solutions\watchful-eye\WatchfulEye\resource.rc
// //
#define IDD_DIALOGMAIN 101 #define IDD_DIALOGMAIN 101
#define IDC_STATICTIME 1000 #define IDC_STATICUPPER 1000
#define IDC_STATICUPPER 1001
// Next default values for new objects // Next default values for new objects
// //