-1

so a quick rundown of the Win32 app I'm making. It's basically supposed to change refresh rate between 60 and 144 Hz based on whether or not the laptop is plugged in. When I launch the app, the GUI starts but it crashes. I'll post the code and debug below.

#ifndef UNICODE
#define UNICODE
#define UNICODE_WAS_UNDEFINED
#endif

#include <Windows.h>

#ifdef UNICODE_WAS_UNDEFINED
#undef UNICODE
#endif
#include <iostream>

using namespace std;

BOOL checked = FALSE;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

    MSG msg;
    WNDCLASS wc = { 0 };
    wc.lpszClassName = L"autoRefresh";
    wc.hInstance = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);


    RegisterClass(&wc);
    HWND hWnd = CreateWindowW(wc.lpszClassName, L"Refresh Changer", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 860, 540, 500, 150, 0, 0, hInstance, 0);

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    RegisterPowerSettingNotification(hWnd, &GUID_ACDC_POWER_SOURCE, DEVICE_NOTIFY_WINDOW_HANDLE);

    return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    DEVMODE dm;
    ZeroMemory(&dm, sizeof(dm));
    dm.dmSize = sizeof(dm);

    switch (msg) {
    case WM_CREATE: {
        CreateWindow(TEXT("button"), TEXT("Enable automatic refresh rate changer (Will run at startup)"), WS_VISIBLE | WS_CHILD | BS_CHECKBOX, 20, 20, 500, 35, hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
        CheckDlgButton(hwnd, 1, BST_UNCHECKED);
        break;
    }

    case WM_COMMAND: {
        OutputDebugStringW(L"WM_COMMAND case\n");
        checked = IsDlgButtonChecked(hwnd, 1);
        if (checked) {
            OutputDebugStringW(L"Box unchecked\n");
            CheckDlgButton(hwnd, 1, BST_UNCHECKED);
            checked = FALSE;
        }
        else {
            OutputDebugStringW(L"Box checked\n");
            CheckDlgButton(hwnd, 1, BST_CHECKED);
            checked = TRUE;
        }
        break;
    }

    case WM_POWERBROADCAST: {
        OutputDebugStringW(L"WM_BROADCAST case\n");
        if (checked) {
            OutputDebugStringW(L"WM_BROADCAST checked is TRUE\n");
            //std::wstring progPath = L"C:\\Users\\user\\AppData\\Roaming\\Microsoft\\Windows\\RefreshChanger.exe";
            //HKEY hkey = NULL;
            //LONG createStatus = RegCreateKey(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &hkey); //Creates a key       
            //LONG status = RegSetValueEx(hkey, L"RefreshChanger", 0, REG_SZ, (BYTE*)progPath.c_str(), (progPath.size() + 1) * sizeof(wchar_t));

            SYSTEM_POWER_STATUS powerStatus;
            GetSystemPowerStatus(&powerStatus);
            if (powerStatus.ACLineStatus == 1) {
                OutputDebugStringW(L"Refresh rate before changing: " + dm.dmDisplayFrequency);
                dm.dmDisplayFrequency = 144;
                LONG ret = ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, NULL);
                OutputDebugStringW(L"ChangeDisplaySettingsEx returned " + ret);
                if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)) {
                    OutputDebugStringW(L"Refresh rate after changing: " + dm.dmDisplayFrequency);
                }
                switch (ret) {
                case DISP_CHANGE_SUCCESSFUL:
                    OutputDebugStringW(L"Display successfully changed\n");
                    break;
                case DISP_CHANGE_BADDUALVIEW:
                    OutputDebugStringW(L"The settings change was unsuccessful because the system is DualView capable\n");
                    break;
                case DISP_CHANGE_BADFLAGS:
                    OutputDebugStringW(L"An invalid set of flags was passed in.\n");
                    break;
                case DISP_CHANGE_BADMODE:
                    OutputDebugStringW(L"The graphics mode is not supported.\n");
                    break;
                case DISP_CHANGE_BADPARAM:
                    OutputDebugStringW(L"An invalid parameter was passed in. This can include an invalid flag or combination of flags.\n");
                    break;
                case DISP_CHANGE_FAILED:
                    OutputDebugStringW(L"The display driver failed the specified graphics mode.\n");
                    break;
                case DISP_CHANGE_NOTUPDATED:
                    OutputDebugStringW(L"Unable to write settings to the registry.\n");
                    break;
                case DISP_CHANGE_RESTART:
                    OutputDebugStringW(L"The computer must be restarted for the graphics mode to work.\n");
                    break;
                }//switch

            }
            else {
                OutputDebugStringW(L"WM_BROADCAST checked is FALSE\n");
                OutputDebugStringW(L"Refresh rate before changing: " + dm.dmDisplayFrequency);
                dm.dmDisplayFrequency = 60;
                LONG ret = ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, NULL);
                OutputDebugStringW(L"ChangeDisplaySettingsEx returned " + ret);
                if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)) {
                    OutputDebugStringW(L"Refresh rate after changing: " + dm.dmDisplayFrequency);
                }
                switch (ret) {
                case DISP_CHANGE_SUCCESSFUL:
                    OutputDebugStringW(L"Display successfully changed\n");
                    break;
                case DISP_CHANGE_BADDUALVIEW:
                    OutputDebugStringW(L"The settings change was unsuccessful because the system is DualView capable\n");
                    break;
                case DISP_CHANGE_BADFLAGS:
                    OutputDebugStringW(L"An invalid set of flags was passed in.\n");
                    break;
                case DISP_CHANGE_BADMODE:
                    OutputDebugStringW(L"The graphics mode is not supported.\n");
                    break;
                case DISP_CHANGE_BADPARAM:
                    OutputDebugStringW(L"An invalid parameter was passed in. This can include an invalid flag or combination of flags.\n");
                    break;
                case DISP_CHANGE_FAILED:
                    OutputDebugStringW(L"The display driver failed the specified graphics mode.\n");
                    break;
                case DISP_CHANGE_NOTUPDATED:
                    OutputDebugStringW(L"Unable to write settings to the registry.\n");
                    break;
                case DISP_CHANGE_RESTART:
                    OutputDebugStringW(L"The computer must be restarted for the graphics mode to work.\n");
                }//switch
            }//if/else
        }//if checked
    }//case

    case WM_DESTROY: {
        OutputDebugStringW(L"WM_DESTROY case\n");
        PostQuitMessage(0);
        break;
    }

    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

And here's a screenshot of the debug console:

Debug console

When I unplug the charger, the GUI crashes. It will run from being unplugged, but it also crashes when I plug the charger in. The refresh rate isn't changed and WM_DESTROY gets called, even though I'm not clicking the X at the top of the window. I'm super new to Win32 so I'm sorry if I'm missing something super simple. My background is primarily in Android development. Thanks for any help!

daniel-eh
  • 344
  • 3
  • 13
  • 1
    *And here's a screenshot of the debug console:* -- Run your program under the debugger and check the call stack when the crash occurs. – PaulMcKenzie Sep 15 '20 at 21:28
  • 3
    If you set `dm.dmDisplayFrequency`, then you must also set the bit `DM_DISPLAYFREQUENCY` in `dm.dmFields` to indicate that the field is initialized. – Andreas Wenzel Sep 15 '20 at 21:42
  • Thanks for that, Andreas! That was the issue for the refresh rate not changing. I appreciate it. – daniel-eh Sep 15 '20 at 21:57

1 Answers1

3

You're not breaking out of your outer switch/case so you're falling through into the WM_DESTROY case.

jkb
  • 2,376
  • 1
  • 9
  • 12