Add double-buffering - No more flicker!
This commit is contained in:
parent
1763bf72da
commit
f11b6abeec
@ -39,6 +39,8 @@ namespace watchfuleye {
|
|||||||
, m_greenBrush(nullptr)
|
, m_greenBrush(nullptr)
|
||||||
, m_yellowBrush(nullptr)
|
, m_yellowBrush(nullptr)
|
||||||
, m_redBrush(nullptr)
|
, m_redBrush(nullptr)
|
||||||
|
, m_offscreenDC(nullptr)
|
||||||
|
, m_offscreenBitmap(nullptr)
|
||||||
{
|
{
|
||||||
std::cout << std::format("{} {}\n", m_appName, m_appVersion);
|
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_yellowBrush = CreateSolidBrush(RGB(255, 255, 150));
|
||||||
app->m_redBrush = CreateSolidBrush(RGB(255, 150, 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);
|
SendMessage(hWnd, WM_UPDATE, NULL, NULL);
|
||||||
SetTimer(hWnd, IDT_UPDATE, 1000, nullptr);
|
SetTimer(hWnd, IDT_UPDATE, 200, nullptr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -167,7 +169,7 @@ namespace watchfuleye {
|
|||||||
if (HIWORD(wParam) == 0 && LOWORD(wParam) == IDM_ABOUT) {
|
if (HIWORD(wParam) == 0 && LOWORD(wParam) == IDM_ABOUT) {
|
||||||
MessageBox(hWnd, std::format("{} {}\nCopyright Grayson Riffe 2026\ngraysonriffe.com\n\n"
|
MessageBox(hWnd, std::format("{} {}\nCopyright Grayson Riffe 2026\ngraysonriffe.com\n\n"
|
||||||
"\t{} is a simple countdown application\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,
|
"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);
|
app->m_appName).c_str(), std::format("About {}", app->m_appName).c_str(), MB_OK);
|
||||||
|
|
||||||
@ -198,12 +200,32 @@ namespace watchfuleye {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_ERASEBKGND: {
|
case WM_ERASEBKGND: { // Don't erase the background, it is already done in WM_PAINT
|
||||||
HDC hDC = reinterpret_cast<HDC>(wParam);
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_PAINT: {
|
||||||
|
PAINTSTRUCT ps = {};
|
||||||
|
HDC hDC = BeginPaint(hWnd, &ps);
|
||||||
|
|
||||||
RECT clientRect = {};
|
RECT clientRect = {};
|
||||||
GetClientRect(hWnd, &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;
|
HBRUSH backgroundBrush = nullptr;
|
||||||
|
|
||||||
if (!app->m_active)
|
if (!app->m_active)
|
||||||
@ -215,25 +237,11 @@ namespace watchfuleye {
|
|||||||
else
|
else
|
||||||
backgroundBrush = app->m_yellowBrush;
|
backgroundBrush = app->m_yellowBrush;
|
||||||
|
|
||||||
FillRect(hDC, &clientRect, backgroundBrush);
|
FillRect(app->m_offscreenDC, &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 };
|
|
||||||
|
|
||||||
// Setup text options
|
// Setup text options
|
||||||
SetTextColor(hDC, RGB(0, 0, 0));
|
SetTextColor(app->m_offscreenDC, RGB(0, 0, 0));
|
||||||
SetBkMode(hDC, TRANSPARENT);
|
SetBkMode(app->m_offscreenDC, TRANSPARENT);
|
||||||
|
|
||||||
// Calculate time
|
// Calculate time
|
||||||
Seconds elapsed = Duration(Clock::now() - app->m_startTime).count();
|
Seconds elapsed = Duration(Clock::now() - app->m_startTime).count();
|
||||||
@ -242,29 +250,33 @@ namespace watchfuleye {
|
|||||||
remaining -= elapsed;
|
remaining -= elapsed;
|
||||||
|
|
||||||
if (!app->m_active || (app->m_active && !app->m_overTime)) { // Draw time
|
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;
|
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)
|
if (!app->m_active) { // Ready (green)
|
||||||
SelectObject(hDC, app->m_lowerFont);
|
SelectObject(app->m_offscreenDC, app->m_lowerFont);
|
||||||
DrawText(hDC, "Ready", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
DrawText(app->m_offscreenDC, "Ready", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
||||||
}
|
}
|
||||||
else if (!app->m_overTime) { // Counting (yellow)
|
else if (!app->m_overTime) { // Counting (yellow)
|
||||||
SelectObject(hDC, app->m_lowerFont);
|
SelectObject(app->m_offscreenDC, app->m_lowerFont);
|
||||||
DrawText(hDC, "Time Remaining on Tester", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
DrawText(app->m_offscreenDC, "Time Remaining on Tester", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
||||||
}
|
}
|
||||||
else { // Over time (red)
|
else { // Over time (red)
|
||||||
SelectObject(hDC, app->m_lowerFont);
|
SelectObject(app->m_offscreenDC, app->m_lowerFont);
|
||||||
DrawText(hDC, "Please Eject Your USB", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
DrawText(app->m_offscreenDC, "Please Eject Your USB", -1, &lowerRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
||||||
SelectObject(hDC, app->m_timeFont);
|
SelectObject(app->m_offscreenDC, app->m_timeFont);
|
||||||
DrawText(hDC, "STOP", -1, &timeRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
DrawText(app->m_offscreenDC, "STOP", -1, &timeRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remaining <= 0)
|
if (remaining <= 0)
|
||||||
app->m_overTime = true;
|
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);
|
EndPaint(hWnd, &ps);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -335,5 +347,8 @@ namespace watchfuleye {
|
|||||||
DeleteObject(m_greenBrush);
|
DeleteObject(m_greenBrush);
|
||||||
DeleteObject(m_yellowBrush);
|
DeleteObject(m_yellowBrush);
|
||||||
DeleteObject(m_redBrush);
|
DeleteObject(m_redBrush);
|
||||||
|
|
||||||
|
DeleteObject(m_offscreenBitmap);
|
||||||
|
DeleteDC(m_offscreenDC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,5 +38,7 @@ namespace watchfuleye {
|
|||||||
HRGN m_region;
|
HRGN m_region;
|
||||||
HFONT m_timeFont, m_lowerFont;
|
HFONT m_timeFont, m_lowerFont;
|
||||||
HBRUSH m_greenBrush, m_yellowBrush, m_redBrush;
|
HBRUSH m_greenBrush, m_yellowBrush, m_redBrush;
|
||||||
|
HDC m_offscreenDC;
|
||||||
|
HBITMAP m_offscreenBitmap;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user