mirror of
https://github.com/WCBROW01/WinPowerDMS.git
synced 2025-12-12 10:18:06 -05:00
Compare commits
8 Commits
350e2960b8
...
v0.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
| cedb800012 | |||
| 5911ca0100 | |||
| e4157e70b3 | |||
| a5555b4ee1 | |||
| 01727c04f0 | |||
| e5dbac5879 | |||
| 4dc933d4bc | |||
| 0295d289cf |
10
README.md
10
README.md
@ -2,15 +2,15 @@
|
||||
|
||||
A utility for switching the resolution of your laptop's display based on the current power state.
|
||||
|
||||
Currently a work in progress. Not very useful yet since it doesn't save your preferences. It doesn't even have an icon.
|
||||
Currently a work in progress. It works reasonably well for a standard single display configuration, but other scenarios have not been extensively tested, and there are some edge cases that may need to be worked out.
|
||||
|
||||
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 supports Windows Vista or higher.
|
||||
|
||||
## TODO
|
||||
- [x] Save preferences to the Windows registry.
|
||||
- [x] Add a checkbox to preferences for starting at login.
|
||||
- [ ] Add an icon.
|
||||
- [x] Add an icon.
|
||||
- [ ] Add behavior for when multiple displays are connected.
|
||||
- [x] Warn the user when the system has no battery.
|
||||
- [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.
|
||||
- [ ] Support dark mode.
|
||||
@ -1,3 +1,7 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WIN32_WINNT _WIN32_WINNT_VISTA
|
||||
#define NTDDI_VERSION NTDDI_VISTA
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
@ -28,7 +32,7 @@ BOOL DisplayModeEquals(const DISPLAY_MODE* a, const DISPLAY_MODE* b) {
|
||||
// I hate parsing the string here, but the alternative requires extra memory management.
|
||||
static DISPLAY_MODE GetModeFromCB(HWND hComboBox) {
|
||||
DISPLAY_MODE mode = { 0 };
|
||||
size_t selectedIndex = SendMessage(hComboBox, CB_GETCURSEL, 0, 0);
|
||||
LRESULT selectedIndex = SendMessage(hComboBox, CB_GETCURSEL, 0, 0);
|
||||
if (selectedIndex != CB_ERR) {
|
||||
LRESULT len = SendMessage(hComboBox, CB_GETLBTEXTLEN, selectedIndex, 0);
|
||||
if (len != CB_ERR) {
|
||||
@ -124,7 +128,6 @@ static void TestDisplayMode(HWND hDlg, DISPLAY_MODE* mode) {
|
||||
typedef struct {
|
||||
DISPLAY_MODE modeBatt;
|
||||
DISPLAY_MODE modeAC;
|
||||
DWORD disableBatteryWarning;
|
||||
BOOL runAtStartup;
|
||||
} WINPOWERDMS_PREFS;
|
||||
|
||||
@ -145,7 +148,6 @@ static BOOL SavePrefs(void) {
|
||||
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));
|
||||
RegSetValueEx(regKey, L"Disable Battery Warning", 0, REG_DWORD, &userPrefs.disableBatteryWarning, sizeof(userPrefs.disableBatteryWarning));
|
||||
RegCloseKey(regKey);
|
||||
saved = TRUE;
|
||||
}
|
||||
@ -180,8 +182,6 @@ static BOOL LoadPrefs(void) {
|
||||
RegGetValue(regKey, L"AC Power", L"Height", RRF_RT_REG_DWORD, NULL, &userPrefs.modeAC.height, &keySize);
|
||||
keySize = sizeof(userPrefs.modeAC.refresh);
|
||||
RegGetValue(regKey, L"AC Power", L"Refresh Rate", RRF_RT_REG_DWORD, NULL, &userPrefs.modeAC.refresh, &keySize);
|
||||
keySize = sizeof(userPrefs.disableBatteryWarning);
|
||||
RegGetValue(regKey, NULL, L"Disable Battery Warning", RRF_RT_REG_DWORD, NULL, &userPrefs.disableBatteryWarning, &keySize);
|
||||
RegCloseKey(regKey);
|
||||
loaded = TRUE;
|
||||
}
|
||||
@ -203,13 +203,12 @@ 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 uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
HWND hComboBatt = GetDlgItem(hDlg, IDC_COMBO_BATT);
|
||||
HWND hComboAC = GetDlgItem(hDlg, IDC_COMBO_AC);
|
||||
HWND hCheckBattWarning = GetDlgItem(hDlg, IDC_CHECK_BATT_WARNING);
|
||||
HWND hCheckStartup = GetDlgItem(hCheckBattWarning, IDC_CHECK_STARTUP);
|
||||
HWND hCheckStartup = GetDlgItem(hDlg, IDC_CHECK_STARTUP);
|
||||
|
||||
switch (message) {
|
||||
switch (uMsg) {
|
||||
case WM_INITDIALOG: {
|
||||
// devMode object that will be enumerated
|
||||
DEVMODE devMode;
|
||||
@ -217,7 +216,7 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
|
||||
devMode.dmSize = sizeof(devMode);
|
||||
|
||||
size_t modeCount = 0;
|
||||
int modeNum = 0;
|
||||
DWORD modeNum = 0;
|
||||
DISPLAY_MODE lastMode = { 0 };
|
||||
while (EnumDisplaySettings(NULL, modeNum++, &devMode)) {
|
||||
DISPLAY_MODE currentMode = {
|
||||
@ -246,7 +245,6 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
|
||||
}
|
||||
}
|
||||
|
||||
SendMessage(hCheckBattWarning, BM_SETCHECK, userPrefs.disableBatteryWarning ? BST_CHECKED : BST_UNCHECKED, 0);
|
||||
SendMessage(hCheckStartup, BM_SETCHECK, userPrefs.runAtStartup ? BST_CHECKED : BST_UNCHECKED, 0);
|
||||
return TRUE;
|
||||
}
|
||||
@ -257,7 +255,6 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
|
||||
case IDOK: {
|
||||
userPrefs.modeBatt = GetModeFromCB(hComboBatt);
|
||||
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();
|
||||
if (LOWORD(wParam) == IDC_BUTTON_APPLY) return TRUE;
|
||||
@ -340,7 +337,7 @@ static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
||||
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) {
|
||||
if (!LoadPrefs()) { // set both battery and AC to current display mode if there are no preferences set
|
||||
DISPLAY_MODE currentMode = GetCurrentDisplayMode();
|
||||
userPrefs.modeAC = currentMode;
|
||||
@ -359,11 +356,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
HWND hWnd = CreateWindowEx(0, L"TrayAppClass", NULL, 0, 0, 0, 0, 0,
|
||||
HWND_MESSAGE, NULL, hInstance, NULL);
|
||||
RegisterPowerSettingNotification(hWnd, &GUID_ACDC_POWER_SOURCE, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
|
||||
// Check if there is a battery in the system and display a warning message if there isn't one.
|
||||
SYSTEM_POWER_STATUS powerStatus;
|
||||
if (!userPrefs.disableBatteryWarning && GetSystemPowerStatus(&powerStatus) && powerStatus.BatteryFlag == 128)
|
||||
MessageBox(hWnd, L"There is no battery present in the system. The program will start and set your display mode to what you have set for AC power, but do nothing else afterwards.", L"WinPowerDMS", MB_OK | MB_ICONWARNING);
|
||||
|
||||
// Create context menu
|
||||
hMenu = CreatePopupMenu();
|
||||
@ -372,12 +364,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
AppendMenu(hMenu, MF_STRING, ID_TRAY_EXIT, L"Exit");
|
||||
|
||||
// Setup tray icon
|
||||
HICON hTrayIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
|
||||
nid.cbSize = sizeof(NOTIFYICONDATA);
|
||||
nid.hWnd = hWnd;
|
||||
nid.uID = TRAY_ICON_ID;
|
||||
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
|
||||
nid.uCallbackMessage = WM_TRAYICON;
|
||||
nid.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Replace this with my own icon at some point
|
||||
nid.hIcon = hTrayIcon;
|
||||
wcscpy_s(nid.szTip, sizeof(nid.szTip) / sizeof(nid.szTip[0]), L"WinPowerDMS");
|
||||
|
||||
Shell_NotifyIcon(NIM_ADD, &nid);
|
||||
@ -389,5 +382,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
DestroyIcon(hTrayIcon);
|
||||
return 0;
|
||||
}
|
||||
BIN
WinPowerDMS/WinPowerDMS.ico
Normal file
BIN
WinPowerDMS/WinPowerDMS.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
@ -79,9 +79,14 @@
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ComCtl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<MinimumRequiredVersion>6.0</MinimumRequiredVersion>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>true</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
@ -93,9 +98,14 @@
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ComCtl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<MinimumRequiredVersion>6.0</MinimumRequiredVersion>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>true</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
@ -108,9 +118,10 @@
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ComCtl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<MinimumRequiredVersion>6.0</MinimumRequiredVersion>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
<EnableDpiAwareness>true</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
@ -123,9 +134,14 @@
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ComCtl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<MinimumRequiredVersion>6.0</MinimumRequiredVersion>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>true</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="WinPowerDMS.c" />
|
||||
@ -136,6 +152,9 @@
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="WinPowerDMS.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="WinPowerDMS.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.c">
|
||||
<ClCompile Include="WinPowerDMS.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
@ -29,4 +29,9 @@
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="WinPowerDMS.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -3,20 +3,20 @@
|
||||
// Used by WinPowerDMS.rc
|
||||
//
|
||||
#define IDD_PREFSDIALOG 101
|
||||
#define IDI_APPICON 106
|
||||
#define IDC_COMBO_BATT 1001
|
||||
#define IDC_COMBO_AC 1002
|
||||
#define IDC_BUTTON_TEST_BATT 1003
|
||||
#define IDC_BUTTON_TEST_AC 1004
|
||||
#define IDC_BUTTON_APPLY 1005
|
||||
#define IDC_LIST1 1006
|
||||
#define IDC_CHECK_BATT_WARNING 1007
|
||||
#define IDC_CHECK_STARTUP 1008
|
||||
#define IDC_CHECK_STARTUP 1007
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 104
|
||||
#define _APS_NEXT_RESOURCE_VALUE 107
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1008
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
|
||||
Reference in New Issue
Block a user