diff --git a/WatchfulEye/src/Application.cpp b/WatchfulEye/src/Application.cpp index 9e31d53..9b46006 100644 --- a/WatchfulEye/src/Application.cpp +++ b/WatchfulEye/src/Application.cpp @@ -39,6 +39,8 @@ namespace watchfuleye { , m_greenBrush(nullptr) , m_yellowBrush(nullptr) , m_redBrush(nullptr) + , m_offscreenDC(nullptr) + , m_offscreenBitmap(nullptr) { std::cout << std::format("{} {}\n", m_appName, m_appVersion); } @@ -114,9 +116,9 @@ namespace watchfuleye { app->m_yellowBrush = CreateSolidBrush(RGB(255, 255, 150)); app->m_redBrush = CreateSolidBrush(RGB(255, 150, 150)); - // App will update (repaint) every second + // App will update (repaint) at 5 FPS SendMessage(hWnd, WM_UPDATE, NULL, NULL); - SetTimer(hWnd, IDT_UPDATE, 1000, nullptr); + SetTimer(hWnd, IDT_UPDATE, 200, nullptr); return 0; } @@ -167,7 +169,7 @@ namespace watchfuleye { if (HIWORD(wParam) == 0 && LOWORD(wParam) == IDM_ABOUT) { MessageBox(hWnd, std::format("{} {}\nCopyright Grayson Riffe 2026\ngraysonriffe.com\n\n" "\t{} is a simple countdown application\n" - "specifically designed for this electronics testing labratory.\n\n" + "specifically designed for this electronics testing labratory.\n" "Hopefully, it's working!", app->m_appName, app->m_appVersion, app->m_appName).c_str(), std::format("About {}", app->m_appName).c_str(), MB_OK); @@ -198,12 +200,32 @@ namespace watchfuleye { return 0; } - case WM_ERASEBKGND: { - HDC hDC = reinterpret_cast(wParam); + case WM_ERASEBKGND: { // Don't erase the background, it is already done in WM_PAINT + return 1; + } + + case WM_PAINT: { + PAINTSTRUCT ps = {}; + HDC hDC = BeginPaint(hWnd, &ps); RECT clientRect = {}; GetClientRect(hWnd, &clientRect); + // Create offscreen buffer if not already created + if (!app->m_offscreenDC) { + app->m_offscreenDC = CreateCompatibleDC(hDC); + app->m_offscreenBitmap = CreateCompatibleBitmap(hDC, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top); + } + + // Setup RECTs + RECT timeRect = clientRect; + timeRect.top -= 25, timeRect.bottom -= 25; + + RECT lowerRect = { .top = WINDOW_HEIGHT - 65, .right = WINDOW_WIDTH, .bottom = WINDOW_HEIGHT }; + + HANDLE prevBitmap = SelectObject(app->m_offscreenDC, app->m_offscreenBitmap); + + // Fill background HBRUSH backgroundBrush = nullptr; if (!app->m_active) @@ -215,25 +237,11 @@ namespace watchfuleye { else backgroundBrush = app->m_yellowBrush; - FillRect(hDC, &clientRect, backgroundBrush); - - return 1; - } - - case WM_PAINT: { - PAINTSTRUCT ps = {}; - HDC hDC = BeginPaint(hWnd, &ps); - - // Setup RECTs - RECT timeRect = {}; - GetClientRect(hWnd, &timeRect); - timeRect.top -= 25, timeRect.bottom -= 25; - - RECT lowerRect = { .top = WINDOW_HEIGHT - 65, .right = WINDOW_WIDTH, .bottom = WINDOW_HEIGHT }; + FillRect(app->m_offscreenDC, &clientRect, backgroundBrush); // Setup text options - SetTextColor(hDC, RGB(0, 0, 0)); - SetBkMode(hDC, TRANSPARENT); + SetTextColor(app->m_offscreenDC, RGB(0, 0, 0)); + SetBkMode(app->m_offscreenDC, TRANSPARENT); // Calculate time Seconds elapsed = Duration(Clock::now() - app->m_startTime).count(); @@ -242,29 +250,33 @@ namespace watchfuleye { remaining -= elapsed; if (!app->m_active || (app->m_active && !app->m_overTime)) { // Draw time - SelectObject(hDC, app->m_timeFont); + SelectObject(app->m_offscreenDC, app->m_timeFont); 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); + DrawText(app->m_offscreenDC, std::format("{:02}:{:02}", minutes, seconds).c_str(), -1, &timeRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER); } if (!app->m_active) { // Ready (green) - SelectObject(hDC, app->m_lowerFont); - DrawText(hDC, "Ready", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER); + SelectObject(app->m_offscreenDC, app->m_lowerFont); + DrawText(app->m_offscreenDC, "Ready", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER); } else if (!app->m_overTime) { // Counting (yellow) - SelectObject(hDC, app->m_lowerFont); - DrawText(hDC, "Time Remaining on Tester", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER); + SelectObject(app->m_offscreenDC, app->m_lowerFont); + DrawText(app->m_offscreenDC, "Time Remaining on Tester", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER); } else { // Over time (red) - SelectObject(hDC, app->m_lowerFont); - DrawText(hDC, "Please Eject Your USB", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER); - SelectObject(hDC, app->m_timeFont); - DrawText(hDC, "STOP", -1, &timeRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER); + SelectObject(app->m_offscreenDC, app->m_lowerFont); + DrawText(app->m_offscreenDC, "Please Eject Your USB", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER); + SelectObject(app->m_offscreenDC, app->m_timeFont); + DrawText(app->m_offscreenDC, "STOP", -1, &timeRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER); } if (remaining <= 0) app->m_overTime = true; + BitBlt(hDC, 0, 0, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, app->m_offscreenDC, 0, 0, SRCCOPY); + + SelectObject(app->m_offscreenDC, prevBitmap); + EndPaint(hWnd, &ps); return 0; } @@ -335,5 +347,8 @@ namespace watchfuleye { DeleteObject(m_greenBrush); DeleteObject(m_yellowBrush); DeleteObject(m_redBrush); + + DeleteObject(m_offscreenBitmap); + DeleteDC(m_offscreenDC); } } diff --git a/WatchfulEye/src/Application.h b/WatchfulEye/src/Application.h index 5b27d7b..768a928 100644 --- a/WatchfulEye/src/Application.h +++ b/WatchfulEye/src/Application.h @@ -38,5 +38,7 @@ namespace watchfuleye { HRGN m_region; HFONT m_timeFont, m_lowerFont; HBRUSH m_greenBrush, m_yellowBrush, m_redBrush; + HDC m_offscreenDC; + HBITMAP m_offscreenBitmap; }; }