Win32 Event Handlng-检查充电器是否已插入

问题描述

我正在尝试使用C ++制作我的第一个Windows应用程序,而且我真的在如何实现事件处理程序方面苦苦挣扎。我正在阅读Win32文档,但是它在示例上确实很少。不幸的是,除了制作第一个窗口之外,我似乎在YouTube或其他书面资源上找不到更多的东西。

我的应用程序的基本思想是让它根据是否插入笔记本电脑的充电器来更改显示屏的刷新率。这主要供个人使用,因为我的笔记本电脑支持144Hz和60Hz,希望在插入时利用更高的速率,但在拔出时获得更长的电池寿命(无需每次插入/拔出都会经历显示设置的烦恼)。

我的背景主要是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。到目前为止,这就是我所得到的(很多复制/粘贴工作都是经过修改的):

#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,hInstance,0);  

    while(GetMessage(&msg,NULL,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,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,BST_CHECKED);
                SetwindowText(hwnd,title);
            }
            break;
        }

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

    }

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

关于GUI方面,至少对于第一个版本,这是我所需要的。但是我真的对注册电源事件/检查并从那里去感到迷茫。

解决方法

一旦有了窗口句柄hWnd,请调用RegisterPowerSettingNotification函数。

RegisterPowerSettingNotification(hWnd,&GUID_ACDC_POWER_SOURCE,DEVICE_NOTIFY_WINDOW_HANDLE);

在您的窗口过程中,查找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;
}
,

Registering for Power Events

应用程序收到带有wParam的WM_POWERBROADCAST消息 PBT_POWERSETTINGCHANGE和指向一个 POWERBROADCAST_SETTING结构。

Power Setting GUIDs:

电源设置GUID在WinNT.h中定义。

GUID_ACDC_POWER_SOURCE

5D3E9A59-E9D5-4B00-A6BD-FF34FF516548

系统电源已更改。数据成员是具有以下内容的DWORD: 来自SYSTEM_POWER_CONDITION枚举的值指示 当前电源。

PoAc(0)-计算机由交流电源(或类似的电源, 例如由12V汽车适配器供电的笔记本电脑。

PoDc(1)-笔记本计算机由板载电池电源供电。

PoHot(2)-笔记本计算机由短期电源供电,例如 作为UPS设备。

某些代码:

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

HPOWERNOTIFY hPowerNotify;
hPowerNotify = RegisterPowerSettingNotification(hWnd,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,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;
    ...