Add functionality for running at startup and disabling the battery warning

This commit is contained in:
2025-08-09 16:03:40 -04:00
parent 036a20df3f
commit 350e2960b8
4 changed files with 47 additions and 18 deletions

View File

@ -8,7 +8,7 @@ This is a simple C program written using Visual Studio 2022 that has no external
## TODO ## TODO
- [x] Save preferences to the Windows registry. - [x] Save preferences to the Windows registry.
- [ ] Add a checkbox to preferences for starting at login. - [x] Add a checkbox to preferences for starting at login.
- [ ] Add an icon. - [ ] Add an icon.
- [ ] Add behavior for when multiple displays are connected. - [ ] Add behavior for when multiple displays are connected.
- [x] Warn the user when the system has no battery. - [x] Warn the user when the system has no battery.

View File

@ -26,9 +26,8 @@ BOOL DisplayModeEquals(const DISPLAY_MODE* a, const DISPLAY_MODE* b) {
#define MODE_SELECTED(mode) (!DisplayModeEquals(&mode, &(DISPLAY_MODE) { 0 })) #define MODE_SELECTED(mode) (!DisplayModeEquals(&mode, &(DISPLAY_MODE) { 0 }))
// I hate parsing the string here, but the alternative requires extra memory management. // I hate parsing the string here, but the alternative requires extra memory management.
static DISPLAY_MODE GetModeFromCB(HWND hDlg, int nIDDlgItem) { static DISPLAY_MODE GetModeFromCB(HWND hComboBox) {
DISPLAY_MODE mode = { 0 }; DISPLAY_MODE mode = { 0 };
HWND hComboBox = GetDlgItem(hDlg, nIDDlgItem);
size_t selectedIndex = SendMessage(hComboBox, CB_GETCURSEL, 0, 0); size_t selectedIndex = SendMessage(hComboBox, CB_GETCURSEL, 0, 0);
if (selectedIndex != CB_ERR) { if (selectedIndex != CB_ERR) {
LRESULT len = SendMessage(hComboBox, CB_GETLBTEXTLEN, selectedIndex, 0); LRESULT len = SendMessage(hComboBox, CB_GETLBTEXTLEN, selectedIndex, 0);
@ -125,14 +124,16 @@ static void TestDisplayMode(HWND hDlg, DISPLAY_MODE* mode) {
typedef struct { typedef struct {
DISPLAY_MODE modeBatt; DISPLAY_MODE modeBatt;
DISPLAY_MODE modeAC; DISPLAY_MODE modeAC;
DWORD disableBatteryWarning; // not used yet DWORD disableBatteryWarning;
BOOL runAtStartup; // not used yet BOOL runAtStartup;
} WINPOWERDMS_PREFS; } WINPOWERDMS_PREFS;
static WINPOWERDMS_PREFS userPrefs = { 0 }; static WINPOWERDMS_PREFS userPrefs = { 0 };
// Save user preferences to registry. // Save user preferences to registry.
static BOOL SavePrefs(void) { static BOOL SavePrefs(void) {
BOOL saved = FALSE;
HKEY regKey; HKEY regKey;
if (!RegCreateKeyEx( if (!RegCreateKeyEx(
HKEY_CURRENT_USER, L"SOFTWARE\\WinPowerDMS", 0, NULL, HKEY_CURRENT_USER, L"SOFTWARE\\WinPowerDMS", 0, NULL,
@ -145,13 +146,26 @@ static BOOL SavePrefs(void) {
RegSetKeyValue(regKey, L"AC Power", L"Height", REG_DWORD, &userPrefs.modeAC.height, sizeof(userPrefs.modeAC.height)); RegSetKeyValue(regKey, L"AC Power", L"Height", REG_DWORD, &userPrefs.modeAC.height, sizeof(userPrefs.modeAC.height));
RegSetKeyValue(regKey, L"AC Power", L"Refresh Rate", REG_DWORD, &userPrefs.modeAC.refresh, sizeof(userPrefs.modeAC.refresh)); RegSetKeyValue(regKey, L"AC Power", L"Refresh Rate", REG_DWORD, &userPrefs.modeAC.refresh, sizeof(userPrefs.modeAC.refresh));
RegSetValueEx(regKey, L"Disable Battery Warning", 0, REG_DWORD, &userPrefs.disableBatteryWarning, sizeof(userPrefs.disableBatteryWarning)); RegSetValueEx(regKey, L"Disable Battery Warning", 0, REG_DWORD, &userPrefs.disableBatteryWarning, sizeof(userPrefs.disableBatteryWarning));
return TRUE; RegCloseKey(regKey);
saved = TRUE;
} }
else return FALSE;
// Create the startup entry
if (userPrefs.runAtStartup) {
WCHAR exePath[MAX_PATH];
DWORD exePathLen = GetModuleFileName(NULL, exePath, sizeof(exePath) / sizeof(exePath[0])) + 1;
RegSetKeyValue(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", L"WinPowerDMS", REG_SZ, exePath, exePathLen);
}
else { // Delete the startup entry
RegDeleteKeyValue(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", L"WinPowerDMS");
}
return saved;
} }
// Load user preferences from registry. // Load user preferences from registry.
static BOOL LoadPrefs(void) { static BOOL LoadPrefs(void) {
BOOL loaded = FALSE;
HKEY regKey; HKEY regKey;
if (!RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\WinPowerDMS", 0, KEY_READ, &regKey)) { if (!RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\WinPowerDMS", 0, KEY_READ, &regKey)) {
DWORD keySize = sizeof(userPrefs.modeBatt.width); DWORD keySize = sizeof(userPrefs.modeBatt.width);
@ -168,9 +182,15 @@ static BOOL LoadPrefs(void) {
RegGetValue(regKey, L"AC Power", L"Refresh Rate", RRF_RT_REG_DWORD, NULL, &userPrefs.modeAC.refresh, &keySize); RegGetValue(regKey, L"AC Power", L"Refresh Rate", RRF_RT_REG_DWORD, NULL, &userPrefs.modeAC.refresh, &keySize);
keySize = sizeof(userPrefs.disableBatteryWarning); keySize = sizeof(userPrefs.disableBatteryWarning);
RegGetValue(regKey, NULL, L"Disable Battery Warning", RRF_RT_REG_DWORD, NULL, &userPrefs.disableBatteryWarning, &keySize); RegGetValue(regKey, NULL, L"Disable Battery Warning", RRF_RT_REG_DWORD, NULL, &userPrefs.disableBatteryWarning, &keySize);
return TRUE; RegCloseKey(regKey);
loaded = TRUE;
} }
else return FALSE;
// Figure out if application has a startup entry
if (!RegGetValue(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", L"WinPowerDMS", RRF_RT_ANY, NULL, NULL, NULL))
userPrefs.runAtStartup = TRUE;
return loaded;
} }
static DISPLAY_MODE GetCurrentDisplayMode(void) { static DISPLAY_MODE GetCurrentDisplayMode(void) {
@ -184,11 +204,13 @@ static DISPLAY_MODE GetCurrentDisplayMode(void) {
} }
static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_INITDIALOG: {
HWND hComboBatt = GetDlgItem(hDlg, IDC_COMBO_BATT); HWND hComboBatt = GetDlgItem(hDlg, IDC_COMBO_BATT);
HWND hComboAC = GetDlgItem(hDlg, IDC_COMBO_AC); HWND hComboAC = GetDlgItem(hDlg, IDC_COMBO_AC);
HWND hCheckBattWarning = GetDlgItem(hDlg, IDC_CHECK_BATT_WARNING);
HWND hCheckStartup = GetDlgItem(hCheckBattWarning, IDC_CHECK_STARTUP);
switch (message) {
case WM_INITDIALOG: {
// devMode object that will be enumerated // devMode object that will be enumerated
DEVMODE devMode; DEVMODE devMode;
ZeroMemory(&devMode, sizeof(devMode)); ZeroMemory(&devMode, sizeof(devMode));
@ -223,6 +245,9 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
lastMode = currentMode; lastMode = currentMode;
} }
} }
SendMessage(hCheckBattWarning, BM_SETCHECK, userPrefs.disableBatteryWarning ? BST_CHECKED : BST_UNCHECKED, 0);
SendMessage(hCheckStartup, BM_SETCHECK, userPrefs.runAtStartup ? BST_CHECKED : BST_UNCHECKED, 0);
return TRUE; return TRUE;
} }
@ -230,8 +255,10 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
switch (LOWORD(wParam)) { switch (LOWORD(wParam)) {
case IDC_BUTTON_APPLY: case IDC_BUTTON_APPLY:
case IDOK: { case IDOK: {
userPrefs.modeBatt = GetModeFromCB(hDlg, IDC_COMBO_BATT); userPrefs.modeBatt = GetModeFromCB(hComboBatt);
userPrefs.modeAC = GetModeFromCB(hDlg, IDC_COMBO_AC); userPrefs.modeAC = GetModeFromCB(hComboAC);
userPrefs.disableBatteryWarning = SendMessage(hCheckBattWarning, BM_GETCHECK, 0, 0) == BST_CHECKED;
userPrefs.runAtStartup = SendMessage(hCheckStartup, BM_GETCHECK, 0, 0) == BST_CHECKED;
SavePrefs(); SavePrefs();
if (LOWORD(wParam) == IDC_BUTTON_APPLY) return TRUE; if (LOWORD(wParam) == IDC_BUTTON_APPLY) return TRUE;
} }
@ -240,12 +267,12 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
return TRUE; return TRUE;
} }
case IDC_BUTTON_TEST_BATT: { case IDC_BUTTON_TEST_BATT: {
DISPLAY_MODE mode = GetModeFromCB(hDlg, IDC_COMBO_BATT); DISPLAY_MODE mode = GetModeFromCB(hComboBatt);
TestDisplayMode(hDlg, &mode); TestDisplayMode(hDlg, &mode);
return TRUE; return TRUE;
} }
case IDC_BUTTON_TEST_AC: { case IDC_BUTTON_TEST_AC: {
DISPLAY_MODE mode = GetModeFromCB(hDlg, IDC_COMBO_AC); DISPLAY_MODE mode = GetModeFromCB(hComboAC);
TestDisplayMode(hDlg, &mode); TestDisplayMode(hDlg, &mode);
return TRUE; return TRUE;
} }

Binary file not shown.

View File

@ -1,6 +1,6 @@
//{{NO_DEPENDENCIES}} //{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file. // Microsoft Visual C++ generated include file.
// Used by PowerDMS.rc // Used by WinPowerDMS.rc
// //
#define IDD_PREFSDIALOG 101 #define IDD_PREFSDIALOG 101
#define IDC_COMBO_BATT 1001 #define IDC_COMBO_BATT 1001
@ -9,6 +9,8 @@
#define IDC_BUTTON_TEST_AC 1004 #define IDC_BUTTON_TEST_AC 1004
#define IDC_BUTTON_APPLY 1005 #define IDC_BUTTON_APPLY 1005
#define IDC_LIST1 1006 #define IDC_LIST1 1006
#define IDC_CHECK_BATT_WARNING 1007
#define IDC_CHECK_STARTUP 1008
// Next default values for new objects // Next default values for new objects
// //
@ -16,7 +18,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104 #define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1007 #define _APS_NEXT_CONTROL_VALUE 1008
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif
#endif #endif