Add drive detection and states
This commit is contained in:
parent
8d070ca5f4
commit
081eb00a46
@ -54,7 +54,7 @@ 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 "Time Remaining on Tester",IDC_STATICUPPER,7,4,286,22,SS_CENTERIMAGE,WS_EX_TRANSPARENT
|
CTEXT "Lower",IDC_STATICLOWER,7,85,286,22,SS_CENTERIMAGE,WS_EX_TRANSPARENT
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -11,19 +11,21 @@
|
|||||||
#define WM_UPDATE WM_USER + 1 // Update window message
|
#define WM_UPDATE WM_USER + 1 // Update window message
|
||||||
|
|
||||||
namespace watchfuleye {
|
namespace watchfuleye {
|
||||||
Application::Application(const char* appName, const char* appVersion, unsigned int maximumMinutes)
|
Application::Application(const char* appName, const char* appVersion, unsigned int maximumMinutes, const char* driveToDetect)
|
||||||
: m_appName(appName)
|
: m_appName(appName)
|
||||||
, m_appVersion(appVersion)
|
, m_appVersion(appVersion)
|
||||||
, m_mainDlg(nullptr)
|
, m_mainDlg(nullptr)
|
||||||
|
, m_running(true)
|
||||||
|
, m_active(false)
|
||||||
|
, m_overTime(false)
|
||||||
, m_maxMinutes(maximumMinutes)
|
, m_maxMinutes(maximumMinutes)
|
||||||
|
, m_drive(driveToDetect)
|
||||||
, m_startTime()
|
, 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);
|
||||||
|
|
||||||
@ -32,19 +34,29 @@ namespace watchfuleye {
|
|||||||
// Create tray icon
|
// Create tray icon
|
||||||
createTrayIcon();
|
createTrayIcon();
|
||||||
|
|
||||||
|
// Create drive query thread
|
||||||
|
std::thread queryThread(&Application::queryThreadFunction, this);
|
||||||
|
|
||||||
ShowWindow(m_mainDlg, SW_SHOW);
|
ShowWindow(m_mainDlg, SW_SHOW);
|
||||||
|
|
||||||
MSG msg = {};
|
MSG msg = {};
|
||||||
while (GetMessage(&msg, nullptr, 0, 0))
|
while (GetMessage(&msg, nullptr, 0, 0))
|
||||||
IsDialogMessage(m_mainDlg, &msg);
|
IsDialogMessage(m_mainDlg, &msg);
|
||||||
|
|
||||||
|
m_running = false;
|
||||||
|
|
||||||
|
queryThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
static HFONT timeFont = nullptr;
|
||||||
|
|
||||||
|
static HBRUSH greenBackgroundBrush = CreateSolidBrush(RGB(150, 255, 150));
|
||||||
|
static HBRUSH yellowBackgroundBrush = CreateSolidBrush(RGB(255, 255, 150));
|
||||||
|
static HBRUSH redBackgroundBrush = CreateSolidBrush(RGB(255, 150, 150));
|
||||||
|
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case WM_INITDIALOG: {
|
case WM_INITDIALOG: {
|
||||||
app = reinterpret_cast<Application*>(lParam);
|
app = reinterpret_cast<Application*>(lParam);
|
||||||
@ -55,7 +67,7 @@ namespace watchfuleye {
|
|||||||
// Spawn in the lower right corner of the virtual screen (might be problematic in some cases)
|
// 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 cornerX = GetSystemMetrics(SM_XVIRTUALSCREEN) + GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||||
int cornerY = GetSystemMetrics(SM_YVIRTUALSCREEN) + GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
int cornerY = GetSystemMetrics(SM_YVIRTUALSCREEN) + GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||||
SetWindowPos(dlg, nullptr, cornerX - 550, cornerY - 340, NULL, NULL, SWP_NOZORDER | SWP_NOSIZE);
|
SetWindowPos(dlg, nullptr, cornerX - 550, cornerY - 540, NULL, NULL, SWP_NOZORDER | SWP_NOSIZE);
|
||||||
|
|
||||||
taskbarCreatedMessage = RegisterWindowMessage("TaskbarCreated");
|
taskbarCreatedMessage = RegisterWindowMessage("TaskbarCreated");
|
||||||
|
|
||||||
@ -64,7 +76,7 @@ namespace watchfuleye {
|
|||||||
strcpy(lFont.lfFaceName, "Consolas");
|
strcpy(lFont.lfFaceName, "Consolas");
|
||||||
lFont.lfHeight = 45;
|
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_STATICLOWER), WM_SETFONT, reinterpret_cast<WPARAM>(upperFont), NULL);
|
||||||
|
|
||||||
lFont.lfHeight = 200;
|
lFont.lfHeight = 200;
|
||||||
lFont.lfWeight = FW_BOLD;
|
lFont.lfWeight = FW_BOLD;
|
||||||
@ -77,7 +89,8 @@ namespace watchfuleye {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case WM_TRAYICON: {
|
case WM_TRAYICON: {
|
||||||
if (LOWORD(lParam) == WM_RBUTTONDOWN) {
|
if (LOWORD(lParam) == WM_LBUTTONDOWN ||
|
||||||
|
LOWORD(lParam) == WM_RBUTTONDOWN) {
|
||||||
SetForegroundWindow(dlg);
|
SetForegroundWindow(dlg);
|
||||||
|
|
||||||
POINT cursor = {};
|
POINT cursor = {};
|
||||||
@ -106,6 +119,18 @@ namespace watchfuleye {
|
|||||||
|
|
||||||
RECT clientRect = {};
|
RECT clientRect = {};
|
||||||
GetClientRect(dlg, &clientRect);
|
GetClientRect(dlg, &clientRect);
|
||||||
|
|
||||||
|
HBRUSH backgroundBrush = nullptr;
|
||||||
|
|
||||||
|
if (!app->m_active)
|
||||||
|
backgroundBrush = greenBackgroundBrush;
|
||||||
|
|
||||||
|
else if (app->m_overTime)
|
||||||
|
backgroundBrush = redBackgroundBrush;
|
||||||
|
|
||||||
|
else
|
||||||
|
backgroundBrush = yellowBackgroundBrush;
|
||||||
|
|
||||||
FillRect(hDC, &clientRect, backgroundBrush);
|
FillRect(hDC, &clientRect, backgroundBrush);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -141,17 +166,29 @@ namespace watchfuleye {
|
|||||||
|
|
||||||
RECT timeRect = {};
|
RECT timeRect = {};
|
||||||
GetClientRect(dlg, &timeRect);
|
GetClientRect(dlg, &timeRect);
|
||||||
timeRect.top += 15, timeRect.bottom += 15;
|
timeRect.top -= 25, timeRect.bottom -= 25;
|
||||||
SetTextColor(hDC, RGB(0, 0, 0));
|
SetTextColor(hDC, RGB(0, 0, 0));
|
||||||
SetBkMode(hDC, TRANSPARENT);
|
SetBkMode(hDC, TRANSPARENT);
|
||||||
SelectObject(hDC, timeFont);
|
SelectObject(hDC, timeFont);
|
||||||
|
|
||||||
Seconds elapsed = Duration(Clock::now() - app->m_startTime).count();
|
Seconds elapsed = Duration(Clock::now() - app->m_startTime).count();
|
||||||
|
if (!app->m_active)
|
||||||
|
elapsed = 0;
|
||||||
|
|
||||||
Seconds remaining = app->m_maxMinutes * 60 - elapsed;
|
Seconds remaining = app->m_maxMinutes * 60 - elapsed;
|
||||||
|
|
||||||
unsigned int minutes = remaining % (3600) / 60, seconds = remaining % 60;
|
if (app->m_overTime) {
|
||||||
|
SetDlgItemText(dlg, IDC_STATICLOWER, "Please Eject Your USB");
|
||||||
|
DrawText(hDC, "STOP", -1, &timeRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SetDlgItemText(dlg, IDC_STATICLOWER, "Time Remaining on Tester");
|
||||||
|
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(hDC, std::format("{:02}:{:02}", minutes, seconds).c_str(), -1, &timeRect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
|
if (remaining <= 0)
|
||||||
|
app->m_overTime = true;
|
||||||
|
|
||||||
EndPaint(dlg, &ps);
|
EndPaint(dlg, &ps);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -186,7 +223,23 @@ namespace watchfuleye {
|
|||||||
Shell_NotifyIcon(NIM_ADD, &iconData);
|
Shell_NotifyIcon(NIM_ADD, &iconData);
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
void Application::queryThreadFunction() {
|
||||||
|
char buff[100] = {};
|
||||||
|
|
||||||
|
while (m_running) {
|
||||||
|
bool driveDetected = QueryDosDevice(m_drive, buff, 100) > 0;
|
||||||
|
|
||||||
|
if (driveDetected && !m_active) {
|
||||||
|
m_active = true;
|
||||||
|
m_startTime = Clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (!driveDetected && m_active) {
|
||||||
|
m_active = false;
|
||||||
|
m_overTime = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,20 +8,26 @@ namespace watchfuleye {
|
|||||||
using Seconds = int;
|
using Seconds = int;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Application(const char* appName, const char* appVersion, unsigned int maximumMinutes);
|
Application(const char* appName, const char* appVersion, unsigned int maximumMinutes, const char* driveToDetect);
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
~Application();
|
|
||||||
private:
|
private:
|
||||||
static BOOL CALLBACK mainDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
static BOOL CALLBACK mainDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
void createTrayIcon();
|
void createTrayIcon();
|
||||||
|
|
||||||
|
void queryThreadFunction();
|
||||||
|
|
||||||
std::string m_appName, m_appVersion;
|
std::string m_appName, m_appVersion;
|
||||||
HWND m_mainDlg;
|
HWND m_mainDlg;
|
||||||
|
|
||||||
|
bool m_running; // Is the application running?
|
||||||
|
bool m_active; // Is the timer ticking?
|
||||||
|
bool m_overTime; // Are we out of time?
|
||||||
|
|
||||||
unsigned int m_maxMinutes;
|
unsigned int m_maxMinutes;
|
||||||
|
const char* m_drive;
|
||||||
|
|
||||||
TimePoint m_startTime;
|
TimePoint m_startTime;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,9 +11,12 @@ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
|||||||
|
|
||||||
#define APPNAME "Watchful Eye"
|
#define APPNAME "Watchful Eye"
|
||||||
|
|
||||||
|
#define MAX_MINUTES 1
|
||||||
|
#define DRIVE_TO_DETECT "E:"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
{
|
{
|
||||||
watchfuleye::Application app(APPNAME, APPVERSION, 15);
|
watchfuleye::Application app(APPNAME, APPVERSION, MAX_MINUTES, DRIVE_TO_DETECT);
|
||||||
app.run();
|
app.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
// Windows
|
// Windows
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|||||||
@ -3,7 +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_STATICUPPER 1000
|
#define IDC_STATICLOWER 1000
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
//
|
//
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user