Win32 事件处理 - 检查充电器是否插入

Win32 Event Handlng - Checking if charger is plugged in

我正在尝试使用 C++ 开发我的第一个 Windows 应用程序,但我真的在为如何实现事件处理程序而苦恼。我正在通读 Win32 文档,但示例很少。不幸的是,除了制作第一个 window.

之外,我似乎无法在 YouTube 或其他书面资源中找到更多内容

我的应用程序的基本思想是让它根据笔记本电脑的充电器是否插入来改变显示器的刷新率。这主要供个人使用,因为我的笔记本电脑支持 144Hz 和 60Hz,并且我想在插入时利用更高的速率,但在拔下时获得更长的电池寿命的好处(每次插入时都无需进行显示设置的乏味 in/unplug)。

我的背景主要是 Android 开发,但这一切似乎比那更令人生畏。我遇到过这些链接:

https://docs.microsoft.com/en-us/dotnet/api/microsoft.win32.systemevents.powermodechanged?redirectedfrom=MSDN&view=dotnet-plat-ext-3.1

https://docs.microsoft.com/en-us/dotnet/api/microsoft.win32.powermodechangedeventhandler?view=dotnet-plat-ext-3.1

How to detect when laptop power cable has been disconnected?

这些似乎是我要找的东西,但我完全不知道如何在我的应用程序上下文中实际将它们组合在一起,尽管看起来我可能真的想使用 PowerModeChangedEventHandler。到目前为止,这是我得到的(很多 copy/paste 都经过修改):

#include <Windows.h>

using namespace std;

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

static char *title = TEXT("Refresh Changer");

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    DEVMODE dm;
    ZeroMemory(&dm, sizeof(dm));
    dm.dmSize = sizeof(dm);

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


    RegisterClass(&wc);
    CreateWindow(wc.lpszClassName, title, WS_OVERLAPPEDWINDOW|WS_VISIBLE, 860, 540, 350, 150, 0, 0, hInstance, 0);  

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

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

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

        case WM_COMMAND: {
            BOOL checked = IsDlgButtonChecked(hwnd, 1);
            if (checked) {
                //if/else blocks to check charger status and current refresh rate, then change accordingly
            } else {
                CheckDlgButton(hwnd, 1, BST_CHECKED);
                SetWindowText(hwnd, title);
            }
            break;
        }

        case WM_DESTROY: {
            PostQuitMessage(0);
            break;
        }

    }

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

这就是我在 GUI 方面所需要的全部内容,至少对于第一个版本而言。但我真的对注册权力 events/checking 并从那里开始感到迷茫。

Registering for Power Events:

An application receives a WM_POWERBROADCAST message with a wParam of PBT_POWERSETTINGCHANGE and an lParam that points to a POWERBROADCAST_SETTING structure.

Power Setting GUIDs:

Power setting GUIDs are defined in WinNT.h.

GUID_ACDC_POWER_SOURCE

5D3E9A59-E9D5-4B00-A6BD-FF34FF516548

The system power source has changed. The Data member is a DWORD with values from the SYSTEM_POWER_CONDITION enumeration that indicates the current power source.

PoAc (0) - The computer is powered by an AC power source (or similar, such as a laptop powered by a 12V automotive adapter).

PoDc (1) - The computer is powered by an onboard battery power source.

PoHot (2) - The computer is powered by a short-term power source such as a UPS device.

一些代码:

HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

HPOWERNOTIFY hPowerNotify;
hPowerNotify = RegisterPowerSettingNotification(hWnd, &GUID_ACDC_POWER_SOURCE, DEVICE_NOTIFY_WINDOW_HANDLE);
...

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_POWERBROADCAST:
    {
            if (wParam == PBT_POWERSETTINGCHANGE) {
                POWERBROADCAST_SETTING* ppbs = (POWERBROADCAST_SETTING*)lParam;
                if (memcmp(&ppbs->PowerSetting, &GUID_ACDC_POWER_SOURCE, sizeof(GUID)) == 0) {
                    unsigned int power_state = *(unsigned int*)ppbs->Data;
                    if (power_state == 0 ) {
                        //The computer is powered by an AC power source (or similar, such as a laptop powered by a 12V automotive adapter).                            
                    }
                    else if(power_state == 1) {
                        //The computer is powered by an onboard battery power source.
                    }
                    eles if(power_state == 2) {
                     //The computer is powered by a short-term power source such as a UPS device.
                    }
                }
                return 0;
            }
    }
    break;
    ...

获得 window 句柄 hWnd 后,调用 RegisterPowerSettingNotification 函数。

RegisterPowerSettingNotification(hWnd, &GUID_ACDC_POWER_SOURCE, DEVICE_NOTIFY_WINDOW_HANDLE);

在您的 window 过程中,查找 WM_POWERBROADCAST 消息并检查 wParam 电源管理事件。

switch (message)
{
  case WM_POWERBROADCAST:
    if (wParam == PBT_APMPOWERSTATUSCHANGE)
    {
      SYSTEM_POWER_STATUS status;
      if (GetSystemPowerStatus(&status))
      {
         // Look at the status structure for power information
      }
    }
    else if (wParam == PBT_POWERSETTINGCHANGE)
    {
      POWERBROADCAST_SETTING *pSetting = (POWERBROADCAST_SETTING *)lParam;
      // Look at the structure for power information
    }
    break;
}