mirror of
https://github.com/WCBROW01/WinPowerDMS.git
synced 2025-12-12 02:18:05 -05:00
Save and load preferences using the registry
Preferences are now saved and loaded using the registry. They are loaded at application startup and written to the registry every time a change is made. If no preferences are present in the registry yet, the current display mode is used for both battery and AC power.
This commit is contained in:
@ -7,10 +7,10 @@ Currently a work in progress. Not very useful yet since it doesn't save your pre
|
|||||||
This is a simple C program written using Visual Studio 2022 that has no external dependencies. It should support Windows Vista or higher, but this hasn't been tested yet.
|
This is a simple C program written using Visual Studio 2022 that has no external dependencies. It should support Windows Vista or higher, but this hasn't been tested yet.
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
- [ ] Save preferences to the Windows registry.
|
- [x] Save preferences to the Windows registry.
|
||||||
- [ ] Add a checkbox to preferences for starting at login.
|
- [ ] 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.
|
||||||
- [ ] Block program from running when the system has no battery.
|
- [ ] Block program from running when the system has no battery.
|
||||||
- [ ] Make the default display mode the current one instead of the highest resolution if there are no preferences set.
|
- [x] Make the default display mode the current one instead of the highest resolution if there are no preferences set.
|
||||||
- [ ] Make an actual about dialog.
|
- [ ] Make an actual about dialog.
|
||||||
@ -14,14 +14,11 @@ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
|||||||
#define TRAY_ICON_ID 1001
|
#define TRAY_ICON_ID 1001
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int width;
|
DWORD width;
|
||||||
int height;
|
DWORD height;
|
||||||
int refresh;
|
DWORD refresh;
|
||||||
} DISPLAY_MODE;
|
} DISPLAY_MODE;
|
||||||
|
|
||||||
static DISPLAY_MODE modeBatt = { 0 };
|
|
||||||
static DISPLAY_MODE modeAC = { 0 };
|
|
||||||
|
|
||||||
BOOL DisplayModeEquals(const DISPLAY_MODE* a, const DISPLAY_MODE* b) {
|
BOOL DisplayModeEquals(const DISPLAY_MODE* a, const DISPLAY_MODE* b) {
|
||||||
return a->width == b->width && a->height == b->height && a->refresh == b->refresh;
|
return a->width == b->width && a->height == b->height && a->refresh == b->refresh;
|
||||||
}
|
}
|
||||||
@ -125,6 +122,52 @@ static void TestDisplayMode(HWND hDlg, DISPLAY_MODE* mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DISPLAY_MODE modeBatt;
|
||||||
|
DISPLAY_MODE modeAC;
|
||||||
|
} WINPOWERDMS_PREFS;
|
||||||
|
|
||||||
|
static WINPOWERDMS_PREFS userPrefs = { 0 };
|
||||||
|
|
||||||
|
// Save user preferences to registry.
|
||||||
|
static BOOL SavePrefs(void) {
|
||||||
|
HKEY regKey;
|
||||||
|
if (!RegCreateKeyEx(
|
||||||
|
HKEY_CURRENT_USER, L"SOFTWARE\\WinPowerDMS", 0, NULL,
|
||||||
|
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, ®Key, NULL
|
||||||
|
)) {
|
||||||
|
RegSetKeyValue(regKey, L"Battery", L"Width", REG_DWORD, &userPrefs.modeBatt.width, sizeof(userPrefs.modeBatt.width));
|
||||||
|
RegSetKeyValue(regKey, L"Battery", L"Height", REG_DWORD, &userPrefs.modeBatt.height, sizeof(userPrefs.modeBatt.height));
|
||||||
|
RegSetKeyValue(regKey, L"Battery", L"Refresh Rate", REG_DWORD, &userPrefs.modeBatt.refresh, sizeof(userPrefs.modeBatt.refresh));
|
||||||
|
RegSetKeyValue(regKey, L"AC Power", L"Width", REG_DWORD, &userPrefs.modeAC.width, sizeof(userPrefs.modeAC.width));
|
||||||
|
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));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load user preferences from registry.
|
||||||
|
static BOOL LoadPrefs(void) {
|
||||||
|
HKEY regKey;
|
||||||
|
if (!RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\WinPowerDMS", 0, KEY_READ, ®Key)) {
|
||||||
|
DWORD keySize = sizeof(DWORD);
|
||||||
|
RegGetValue(regKey, L"Battery", L"Width", RRF_RT_REG_DWORD, NULL, &userPrefs.modeBatt.width, &keySize);
|
||||||
|
keySize = sizeof(DWORD);
|
||||||
|
RegGetValue(regKey, L"Battery", L"Height", RRF_RT_REG_DWORD, NULL, &userPrefs.modeBatt.height, &keySize);
|
||||||
|
keySize = sizeof(DWORD);
|
||||||
|
RegGetValue(regKey, L"Battery", L"Refresh Rate", RRF_RT_REG_DWORD, NULL, &userPrefs.modeBatt.refresh, &keySize);
|
||||||
|
keySize = sizeof(DWORD);
|
||||||
|
RegGetValue(regKey, L"AC Power", L"Width", RRF_RT_REG_DWORD, NULL, &userPrefs.modeAC.width, &keySize);
|
||||||
|
keySize = sizeof(DWORD);
|
||||||
|
RegGetValue(regKey, L"AC Power", L"Height", RRF_RT_REG_DWORD, NULL, &userPrefs.modeAC.height, &keySize);
|
||||||
|
keySize = sizeof(DWORD);
|
||||||
|
RegGetValue(regKey, L"AC Power", L"Refresh Rate", RRF_RT_REG_DWORD, NULL, &userPrefs.modeAC.refresh, &keySize);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
switch (message) {
|
||||||
case WM_INITDIALOG: {
|
case WM_INITDIALOG: {
|
||||||
@ -154,21 +197,17 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
|
|||||||
|
|
||||||
// Add to both combo boxes and check if this is the mode that was set.
|
// Add to both combo boxes and check if this is the mode that was set.
|
||||||
SendMessage(hComboBatt, CB_ADDSTRING, 0, (LPARAM)resText);
|
SendMessage(hComboBatt, CB_ADDSTRING, 0, (LPARAM)resText);
|
||||||
if (DisplayModeEquals(&modeBatt, ¤tMode))
|
if (DisplayModeEquals(&userPrefs.modeBatt, ¤tMode))
|
||||||
SendMessage(hComboBatt, CB_SETCURSEL, modeCount, 0);
|
SendMessage(hComboBatt, CB_SETCURSEL, modeCount, 0);
|
||||||
|
|
||||||
SendMessage(hComboAC, CB_ADDSTRING, 0, (LPARAM)resText);
|
SendMessage(hComboAC, CB_ADDSTRING, 0, (LPARAM)resText);
|
||||||
if (DisplayModeEquals(&modeAC, ¤tMode))
|
if (DisplayModeEquals(&userPrefs.modeAC, ¤tMode))
|
||||||
SendMessage(hComboAC, CB_SETCURSEL, modeCount, 0);
|
SendMessage(hComboAC, CB_SETCURSEL, modeCount, 0);
|
||||||
|
|
||||||
++modeCount;
|
++modeCount;
|
||||||
lastMode = currentMode;
|
lastMode = currentMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// select the highest display mode if one hasn't been selected yet
|
|
||||||
if (!MODE_SELECTED(modeBatt)) SendMessage(hComboBatt, CB_SETCURSEL, modeCount - 1, 0);
|
|
||||||
if (!MODE_SELECTED(modeAC)) SendMessage(hComboAC, CB_SETCURSEL, modeCount - 1, 0);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,8 +215,9 @@ 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: {
|
||||||
modeBatt = GetModeFromCB(hDlg, IDC_COMBO_BATT);
|
userPrefs.modeBatt = GetModeFromCB(hDlg, IDC_COMBO_BATT);
|
||||||
modeAC = GetModeFromCB(hDlg, IDC_COMBO_AC);
|
userPrefs.modeAC = GetModeFromCB(hDlg, IDC_COMBO_AC);
|
||||||
|
SavePrefs();
|
||||||
if (LOWORD(wParam) == IDC_BUTTON_APPLY) return TRUE;
|
if (LOWORD(wParam) == IDC_BUTTON_APPLY) return TRUE;
|
||||||
}
|
}
|
||||||
case IDCANCEL: {
|
case IDCANCEL: {
|
||||||
@ -208,18 +248,17 @@ enum TRAY_IDS {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static NOTIFYICONDATA nid;
|
static NOTIFYICONDATA nid;
|
||||||
static HWND hWnd;
|
|
||||||
static HMENU hMenu;
|
static HMENU hMenu;
|
||||||
|
|
||||||
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
case WM_TRAYICON:
|
case WM_TRAYICON:
|
||||||
if (lParam == WM_RBUTTONUP) {
|
if (lParam == WM_RBUTTONUP) {
|
||||||
POINT pt;
|
POINT pt;
|
||||||
GetCursorPos(&pt);
|
GetCursorPos(&pt);
|
||||||
SetForegroundWindow(hwnd); // Required for menu to disappear correctly
|
SetForegroundWindow(hWnd); // Required for menu to disappear correctly
|
||||||
|
|
||||||
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL);
|
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -232,7 +271,7 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
|
|||||||
MessageBoxW(NULL, L"WinPowerDMS\nA utility for switching the resolution of your laptop's display based on the current power state.", L"About", MB_OK | MB_ICONINFORMATION);
|
MessageBoxW(NULL, L"WinPowerDMS\nA utility for switching the resolution of your laptop's display based on the current power state.", L"About", MB_OK | MB_ICONINFORMATION);
|
||||||
break;
|
break;
|
||||||
case ID_TRAY_EXIT:
|
case ID_TRAY_EXIT:
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hWnd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -247,17 +286,28 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
|
|||||||
OutputDebugString(L"Power status changed\n");
|
OutputDebugString(L"Power status changed\n");
|
||||||
SYSTEM_POWER_STATUS powerStatus;
|
SYSTEM_POWER_STATUS powerStatus;
|
||||||
if (GetSystemPowerStatus(&powerStatus)) {
|
if (GetSystemPowerStatus(&powerStatus)) {
|
||||||
ChangeDisplayMode(powerStatus.ACLineStatus ? &modeAC : &modeBatt, CDS_UPDATEREGISTRY);
|
ChangeDisplayMode(powerStatus.ACLineStatus ? &userPrefs.modeAC : &userPrefs.modeBatt, CDS_UPDATEREGISTRY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
||||||
// Initialize the controls
|
if (!LoadPrefs()) { // set both battery and AC to current display mode if there are no preferences set
|
||||||
InitCommonControls();
|
DEVMODE currentMode = { .dmSize = sizeof(currentMode) };
|
||||||
|
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, ¤tMode);
|
||||||
|
DISPLAY_MODE mode = {
|
||||||
|
.width = currentMode.dmPelsWidth,
|
||||||
|
.height = currentMode.dmPelsHeight,
|
||||||
|
.refresh = currentMode.dmDisplayFrequency
|
||||||
|
};
|
||||||
|
userPrefs.modeAC = mode;
|
||||||
|
userPrefs.modeBatt = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitCommonControls(); // Initialize modern controls
|
||||||
|
|
||||||
WNDCLASS wc = { 0 };
|
WNDCLASS wc = { 0 };
|
||||||
wc.lpfnWndProc = WindowProc;
|
wc.lpfnWndProc = WindowProc;
|
||||||
@ -266,7 +316,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
|
|
||||||
RegisterClass(&wc);
|
RegisterClass(&wc);
|
||||||
|
|
||||||
hWnd = CreateWindowEx(0, L"TrayAppClass", NULL, 0, 0, 0, 0, 0,
|
HWND hWnd = CreateWindowEx(0, L"TrayAppClass", NULL, 0, 0, 0, 0, 0,
|
||||||
HWND_MESSAGE, NULL, hInstance, NULL);
|
HWND_MESSAGE, NULL, hInstance, NULL);
|
||||||
RegisterPowerSettingNotification(hWnd, &GUID_ACDC_POWER_SOURCE, DEVICE_NOTIFY_WINDOW_HANDLE);
|
RegisterPowerSettingNotification(hWnd, &GUID_ACDC_POWER_SOURCE, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user