Compare commits

...

13 Commits

Author SHA1 Message Date
cedb800012 Fix annotations for WinMain
Fix "C28251 Inconsistent annotation for function" compiler warning by correctly defining WinMain.
2025-08-15 11:44:51 -07:00
5911ca0100 Update README.md
Update the readme to reflect the current state of the project. The program is much more complete now, and has been tested and works flawlessly on both Windows Vista and 7.
2025-08-14 23:20:15 -07:00
e4157e70b3 Fix 32-bit profiles 2025-08-12 12:40:59 -04:00
a5555b4ee1 Guarantee Vista support
Define NT version headers so that Windows Vista support should reasonably be guaranteed, since we will not be using any newer APIs.
2025-08-12 09:16:34 -04:00
01727c04f0 Remove the battery warning
The battery warning could be annoying, and the option to disable it is confusing to somebody who may never see it.
2025-08-11 15:33:32 -04:00
e5dbac5879 Fix Debug and Release profiles for both x86 and x64
Application now builds with debug and release profiles on both x86 and x64.
2025-08-11 12:55:04 -04:00
4dc933d4bc Update README.md 2025-08-10 13:12:01 -04:00
0295d289cf Create an application icon.
It's quick and dirty but it works well enough.
2025-08-10 01:52:20 -04:00
350e2960b8 Add functionality for running at startup and disabling the battery warning 2025-08-09 16:03:40 -04:00
036a20df3f Display a warning when there is no battery detected 2025-08-09 14:32:15 -04:00
6a586dedb7 Only change video mode if the current video mode matches one of the preferences.
This avoids the program resetting the video mode if you're doing something like testing different resolutions or playing a game in fullscreen.
2025-08-09 13:14:10 -04:00
4b46eafd35 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.
2025-08-09 11:56:59 -04:00
046e8fd2eb Actually enter name in the license. 2025-08-09 11:52:05 -04:00
8 changed files with 170 additions and 55 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) [year] [fullname]
Copyright (c) 2025 Mina Brown
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -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
- [ ] Save preferences to the Windows registry.
- [ ] Add a checkbox to preferences for starting at login.
- [ ] Add an icon.
- [x] Save preferences to the Windows registry.
- [x] Add a checkbox to preferences for starting at login.
- [x] Add an icon.
- [ ] Add behavior for when multiple displays are connected.
- [ ] 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.
- [ ] Support dark mode.

View File

@ -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>
@ -14,14 +18,11 @@ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#define TRAY_ICON_ID 1001
typedef struct {
int width;
int height;
int refresh;
DWORD width;
DWORD height;
DWORD refresh;
} DISPLAY_MODE;
static DISPLAY_MODE modeBatt = { 0 };
static DISPLAY_MODE modeAC = { 0 };
BOOL DisplayModeEquals(const DISPLAY_MODE* a, const DISPLAY_MODE* b) {
return a->width == b->width && a->height == b->height && a->refresh == b->refresh;
}
@ -29,10 +30,9 @@ BOOL DisplayModeEquals(const DISPLAY_MODE* a, const DISPLAY_MODE* b) {
#define MODE_SELECTED(mode) (!DisplayModeEquals(&mode, &(DISPLAY_MODE) { 0 }))
// 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 };
HWND hComboBox = GetDlgItem(hDlg, nIDDlgItem);
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) {
@ -125,19 +125,98 @@ static void TestDisplayMode(HWND hDlg, DISPLAY_MODE* mode) {
}
}
static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_INITDIALOG: {
typedef struct {
DISPLAY_MODE modeBatt;
DISPLAY_MODE modeAC;
BOOL runAtStartup;
} WINPOWERDMS_PREFS;
static WINPOWERDMS_PREFS userPrefs = { 0 };
// Save user preferences to registry.
static BOOL SavePrefs(void) {
BOOL saved = FALSE;
HKEY regKey;
if (!RegCreateKeyEx(
HKEY_CURRENT_USER, L"SOFTWARE\\WinPowerDMS", 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &regKey, 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));
RegCloseKey(regKey);
saved = TRUE;
}
// 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.
static BOOL LoadPrefs(void) {
BOOL loaded = FALSE;
HKEY regKey;
if (!RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\WinPowerDMS", 0, KEY_READ, &regKey)) {
DWORD keySize = sizeof(userPrefs.modeBatt.width);
RegGetValue(regKey, L"Battery", L"Width", RRF_RT_REG_DWORD, NULL, &userPrefs.modeBatt.width, &keySize);
keySize = sizeof(userPrefs.modeBatt.height);
RegGetValue(regKey, L"Battery", L"Height", RRF_RT_REG_DWORD, NULL, &userPrefs.modeBatt.height, &keySize);
keySize = sizeof(userPrefs.modeBatt.refresh);
RegGetValue(regKey, L"Battery", L"Refresh Rate", RRF_RT_REG_DWORD, NULL, &userPrefs.modeBatt.refresh, &keySize);
keySize = sizeof(userPrefs.modeAC.width);
RegGetValue(regKey, L"AC Power", L"Width", RRF_RT_REG_DWORD, NULL, &userPrefs.modeAC.width, &keySize);
keySize = sizeof(userPrefs.modeAC.height);
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);
RegCloseKey(regKey);
loaded = TRUE;
}
// 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) {
DEVMODE currentMode = { .dmSize = sizeof(currentMode) };
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &currentMode);
return (DISPLAY_MODE) {
.width = currentMode.dmPelsWidth,
.height = currentMode.dmPelsHeight,
.refresh = currentMode.dmDisplayFrequency
};
}
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 hCheckStartup = GetDlgItem(hDlg, IDC_CHECK_STARTUP);
switch (uMsg) {
case WM_INITDIALOG: {
// devMode object that will be enumerated
DEVMODE devMode;
ZeroMemory(&devMode, sizeof(devMode));
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 = {
@ -154,11 +233,11 @@ 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.
SendMessage(hComboBatt, CB_ADDSTRING, 0, (LPARAM)resText);
if (DisplayModeEquals(&modeBatt, &currentMode))
if (DisplayModeEquals(&userPrefs.modeBatt, &currentMode))
SendMessage(hComboBatt, CB_SETCURSEL, modeCount, 0);
SendMessage(hComboAC, CB_ADDSTRING, 0, (LPARAM)resText);
if (DisplayModeEquals(&modeAC, &currentMode))
if (DisplayModeEquals(&userPrefs.modeAC, &currentMode))
SendMessage(hComboAC, CB_SETCURSEL, modeCount, 0);
++modeCount;
@ -166,9 +245,7 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
}
}
// 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);
SendMessage(hCheckStartup, BM_SETCHECK, userPrefs.runAtStartup ? BST_CHECKED : BST_UNCHECKED, 0);
return TRUE;
}
@ -176,8 +253,10 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
switch (LOWORD(wParam)) {
case IDC_BUTTON_APPLY:
case IDOK: {
modeBatt = GetModeFromCB(hDlg, IDC_COMBO_BATT);
modeAC = GetModeFromCB(hDlg, IDC_COMBO_AC);
userPrefs.modeBatt = GetModeFromCB(hComboBatt);
userPrefs.modeAC = GetModeFromCB(hComboAC);
userPrefs.runAtStartup = SendMessage(hCheckStartup, BM_GETCHECK, 0, 0) == BST_CHECKED;
SavePrefs();
if (LOWORD(wParam) == IDC_BUTTON_APPLY) return TRUE;
}
case IDCANCEL: {
@ -185,12 +264,12 @@ static INT_PTR CALLBACK PrefsDialogProc(HWND hDlg, UINT message, WPARAM wParam,
return TRUE;
}
case IDC_BUTTON_TEST_BATT: {
DISPLAY_MODE mode = GetModeFromCB(hDlg, IDC_COMBO_BATT);
DISPLAY_MODE mode = GetModeFromCB(hComboBatt);
TestDisplayMode(hDlg, &mode);
return TRUE;
}
case IDC_BUTTON_TEST_AC: {
DISPLAY_MODE mode = GetModeFromCB(hDlg, IDC_COMBO_AC);
DISPLAY_MODE mode = GetModeFromCB(hComboAC);
TestDisplayMode(hDlg, &mode);
return TRUE;
}
@ -208,18 +287,17 @@ enum TRAY_IDS {
};
static NOTIFYICONDATA nid;
static HWND hWnd;
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) {
case WM_TRAYICON:
if (lParam == WM_RBUTTONUP) {
POINT 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;
@ -229,10 +307,10 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_PREFSDIALOG), hWnd, PrefsDialogProc);
break;
case ID_TRAY_ABOUT:
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(hWnd, 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;
case ID_TRAY_EXIT:
DestroyWindow(hwnd);
DestroyWindow(hWnd);
break;
}
break;
@ -245,19 +323,28 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
case WM_POWERBROADCAST:
if (LOWORD(wParam) == PBT_POWERSETTINGCHANGE) {
OutputDebugString(L"Power status changed\n");
DISPLAY_MODE currentMode = GetCurrentDisplayMode();
SYSTEM_POWER_STATUS powerStatus;
if (GetSystemPowerStatus(&powerStatus)) {
ChangeDisplayMode(powerStatus.ACLineStatus ? &modeAC : &modeBatt, CDS_UPDATEREGISTRY);
// Change display mode only if the current display mode is one of the configured options.
if (GetSystemPowerStatus(&powerStatus) &&
(DisplayModeEquals(&currentMode, &userPrefs.modeBatt) || DisplayModeEquals(&currentMode, &userPrefs.modeAC)))
{
ChangeDisplayMode(powerStatus.ACLineStatus ? &userPrefs.modeAC : &userPrefs.modeBatt, CDS_UPDATEREGISTRY);
}
}
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// Initialize the controls
InitCommonControls();
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;
userPrefs.modeBatt = currentMode;
}
InitCommonControls(); // Initialize modern controls
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WindowProc;
@ -266,7 +353,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
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);
RegisterPowerSettingNotification(hWnd, &GUID_ACDC_POWER_SOURCE, DEVICE_NOTIFY_WINDOW_HANDLE);
@ -277,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);
@ -294,5 +382,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
DispatchMessage(&msg);
}
DestroyIcon(hTrayIcon);
return 0;
}

BIN
WinPowerDMS/WinPowerDMS.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

View File

@ -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>

View File

@ -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>

View File

@ -1,22 +1,24 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by PowerDMS.rc
// 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_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 1007
#define _APS_NEXT_CONTROL_VALUE 1008
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif