Add tray icon

This commit is contained in:
Grayson Riffe 2026-06-04 19:41:31 -05:00
parent 1d3e58587d
commit 35b0d02af5
Signed by: grayson
SSH Key Fingerprint: SHA256:23HJg9tnL2m6u0uUb26QIrOTFymFZ+xgSH/2UPEBB/I
4 changed files with 55 additions and 4 deletions

View File

@ -49,12 +49,12 @@ END
// //
IDD_DIALOGMAIN DIALOGEX 0, 0, 300, 114 IDD_DIALOGMAIN DIALOGEX 0, 0, 300, 114
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION STYLE DS_SETFONT | DS_FIXEDSYS | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOPMOST EXSTYLE WS_EX_TOPMOST
CAPTION "Dialog" CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
CTEXT "Time left on tester:",IDC_STATICTIME,17,27,266,60,SS_CENTERIMAGE CTEXT "00:00",IDC_STATICTIME,17,27,266,60,SS_CENTERIMAGE
CTEXT "Time left on tester:",IDC_STATICUPPER,54,4,190,22,SS_CENTERIMAGE CTEXT "Time left on tester:",IDC_STATICUPPER,54,4,190,22,SS_CENTERIMAGE
END END

View File

@ -5,6 +5,9 @@
#include "resource.h" #include "resource.h"
#define WM_TRAYICON WM_USER
#define IDM_EXIT 1001
namespace watchfuleye { namespace watchfuleye {
Application::Application(const char* appName, const char* appVersion) Application::Application(const char* appName, const char* appVersion)
: m_appName(appName) : m_appName(appName)
@ -15,10 +18,14 @@ namespace watchfuleye {
} }
void Application::run() { void Application::run() {
// Create dialog
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
m_mainDlg = CreateDialogParam(nullptr, MAKEINTRESOURCE(IDD_DIALOGMAIN), nullptr, reinterpret_cast<DLGPROC>(mainDlgProc), reinterpret_cast<LPARAM>(this)); m_mainDlg = CreateDialogParam(nullptr, MAKEINTRESOURCE(IDD_DIALOGMAIN), nullptr, reinterpret_cast<DLGPROC>(mainDlgProc), reinterpret_cast<LPARAM>(this));
// Create tray icon
createTrayIcon();
ShowWindow(m_mainDlg, SW_SHOW); ShowWindow(m_mainDlg, SW_SHOW);
MSG msg = {}; MSG msg = {};
@ -28,20 +35,47 @@ 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;
switch (msg) { switch (msg) {
case WM_INITDIALOG: { case WM_INITDIALOG: {
app = reinterpret_cast<Application*>(lParam); app = reinterpret_cast<Application*>(lParam);
SetWindowText(dlg, app->m_appName.c_str()); SetWindowText(dlg, app->m_appName.c_str());
// Set window icons SendMessage(dlg, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION))));
// 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 - 340, NULL, NULL, SWP_NOZORDER | SWP_NOSIZE);
taskbarCreatedMessage = RegisterWindowMessage("TaskbarCreated");
return TRUE;
}
case WM_TRAYICON: {
if (LOWORD(lParam) == WM_RBUTTONDOWN) {
SetForegroundWindow(dlg);
POINT cursor = {};
GetCursorPos(&cursor);
HMENU popupMenu = CreatePopupMenu();
AppendMenu(popupMenu, MF_STRING, IDM_EXIT, "Exit");
TrackPopupMenu(popupMenu, NULL, cursor.x, cursor.y, NULL, dlg, nullptr); // Will block here. Might be problematic.
DestroyMenu(popupMenu);
}
return TRUE;
}
case WM_COMMAND: {
if (HIWORD(wParam) == 0 && LOWORD(wParam) == IDM_EXIT)
DestroyWindow(dlg);
return TRUE; return TRUE;
} }
@ -56,9 +90,23 @@ namespace watchfuleye {
} }
} }
if (msg == taskbarCreatedMessage)
app->createTrayIcon();
return FALSE; return FALSE;
} }
void Application::createTrayIcon() {
NOTIFYICONDATA iconData = {};
iconData.cbSize = sizeof(iconData);
iconData.uVersion = NOTIFYICON_VERSION_4;
iconData.hWnd = m_mainDlg;
iconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
iconData.uCallbackMessage = WM_TRAYICON;
iconData.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
strcpy(iconData.szTip, m_appName.c_str());
Shell_NotifyIcon(NIM_ADD, &iconData);
}
Application::~Application() { Application::~Application() {

View File

@ -11,6 +11,8 @@ namespace watchfuleye {
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();
std::string m_appName, m_appVersion; std::string m_appName, m_appVersion;
HWND m_mainDlg; HWND m_mainDlg;
}; };

View File

@ -9,3 +9,4 @@
// Windows // Windows
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
#include <shellapi.h>