如何在Python中调用Win32 API的PowerRegisterForEffectivePowerModeNotifications?
实现Windows有效电源模式变更的Python回调
因为pywin32未封装PowerRegisterForEffectivePowerModeNotifications API,我们可以直接用ctypes调用Windows原生的powrprof.dll来实现需求。以下是完整的实现方案:
核心思路
Windows的PowerRegisterForEffectivePowerModeNotifications函数用于注册电源模式变更通知,我们需要通过ctypes声明该函数、对应枚举类型和回调函数原型,注册回调后启动消息循环接收通知。
完整代码示例
import ctypes from ctypes import wintypes # 加载电源相关的系统库 powrprof = ctypes.WinDLL('powrprof.dll') user32 = ctypes.WinDLL('user32.dll') # 定义电源模式枚举(对应Windows API中的POWER_MODE) class POWER_MODE(ctypes.c_uint): PowerModeBalanced = 0x00000000 PowerModePerformance = 0x00000001 PowerModeBatterySaver = 0x00000002 PowerModeGame = 0x00000004 # 游戏模式 # 定义通知类型枚举(对应Windows API中的POWER_MODE_NOTIFICATION_TYPE) class POWER_MODE_NOTIFICATION_TYPE(ctypes.c_uint): PowerModeNotificationEffectivePowerMode = 0x00000000 # 定义回调函数的原型 PowerModeCallback = ctypes.WINFUNCTYPE( wintypes.BOOL, wintypes.LPCVOID, # 上下文参数 wintypes.DWORD, # 通知类型 wintypes.LPCVOID # 通知数据(指向POWER_MODE结构) ) # 声明注册通知的API函数 powrprof.PowerRegisterForEffectivePowerModeNotifications.argtypes = [ POWER_MODE_NOTIFICATION_TYPE, PowerModeCallback, wintypes.LPCVOID, wintypes.PHANDLE ] powrprof.PowerRegisterForEffectivePowerModeNotifications.restype = wintypes.DWORD # 声明注销通知的API函数 powrprof.PowerUnregisterPowerSettingNotification.argtypes = [wintypes.HANDLE] powrprof.PowerUnregisterPowerSettingNotification.restype = wintypes.DWORD # 自定义回调逻辑:电源模式变更时触发 def on_power_mode_change(context, notification_type, notification_data): current_mode = ctypes.cast(notification_data, ctypes.POINTER(POWER_MODE)).contents.value mode_map = { POWER_MODE.PowerModeBalanced: "平衡模式", POWER_MODE.PowerModePerformance: "高性能模式", POWER_MODE.PowerModeBatterySaver: "节电模式", POWER_MODE.PowerModeGame: "游戏模式" } print(f"检测到电源模式变更:{mode_map.get(current_mode, f'未知模式(0x{current_mode:08X})')}") return True # 注册通知回调 callback = PowerModeCallback(on_power_mode_change) notification_handle = wintypes.HANDLE() register_result = powrprof.PowerRegisterForEffectivePowerModeNotifications( POWER_MODE_NOTIFICATION_TYPE.PowerModeNotificationEffectivePowerMode, callback, None, ctypes.byref(notification_handle) ) if register_result != 0: raise RuntimeError(f"注册通知失败,错误码: {register_result}") print("已注册电源模式变更监听,按Ctrl+C退出...") # 启动消息循环处理系统通知 try: msg = wintypes.MSG() while user32.GetMessageW(ctypes.byref(msg), None, 0, 0) != 0: user32.TranslateMessage(ctypes.byref(msg)) user32.DispatchMessageW(ctypes.byref(msg)) except KeyboardInterrupt: print("\n正在清理资源...") powrprof.PowerUnregisterPowerSettingNotification(notification_handle) print("监听已注销")
代码说明
- 系统库调用:通过
ctypes直接加载powrprof.dll和user32.dll,调用未被pywin32封装的原生API。 - 枚举类型匹配:严格对应Windows API中的枚举定义,保证参数类型兼容。
- 回调逻辑:
on_power_mode_change会在电源模式(包括游戏模式)切换时触发,解析并输出当前模式。 - 消息循环:Windows的系统通知需要通过消息泵分发,必须启动
GetMessage循环才能接收事件。 - 资源清理:退出时主动注销通知,避免系统资源泄漏。
验证方式
在Windows设置中切换电源模式(比如开启/关闭游戏模式),控制台会实时输出模式变更信息。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

