可以在Windows XP和Linux下挂钩系统电源按钮吗?这样,我的程序会在Windows启动掉电/睡眠事件之前(在PBT_APMQUERYSUSPEND事件发出之前)获得事件?
Windows XP及以下版本:
您需要覆盖程序的主窗口的WndProc函数.在本机不支持此功能的IDE上,可以使用user32 API中的SetWindowLong完成此操作.在自定义WndProc函数中,侦听WM_POWERBROADCAST(0x218)消息.如果收到带有PBT_APMQUERYSUSPEND(0x0)的wParam的消息,请调用所需函数,然后返回BROADCAST_QUERY_DENY(0x424D5144),而不是调用基本WndProc函数.示例代码:
//At program start //GWL_WNDPROC = -4 oldWndProc = SetWindowLong(this.hWnd,GWL_WNDPROC,&MyWndProc) //In MyWndProc(hWnd,wMsg,wParam,lParam) //WM_POWERBROADCAST = 0x218 //PBT_APMQUERYSUSPEND = 0x0 //BROADCAST_QUERY_DENY = 0x424D5144 if wMsg = WM_POWERBROADCAST && wParam = PBT_APMQUERYSUSPEND ( //CALL YOUR FUNCTION HERE! return BROADCAST_QUERY_DENY ) return CallWindowProc(oldWndProc,hWnd,lParam) //Before exiting SetWindowLong(Me.hWnd,oldWndProc)
Windows Vista& up :(感谢Remy Lebeau让我走上正轨)
你需要像XP一样覆盖WndProc,还要调用kernel32 API中的SetThreadExecutionState来禁用睡眠模式,并在user32 API中调用RegisterPowerSettingNotification来监听高级电源通知.您将特别收听GUID_SYSTEM_AWAYMODE通知,该通知在系统被要求进入睡眠状态时发送,但无法执行此操作.要轻松地将字符串转换为正确形成的LPCGUID,您可以在rpcrt4.dll API中使用UuidFromStringA.示例代码:
typedef struct UUID{ int d1,d2,d3,d4 } LPCGUID; //At program start //GWL_WNDPROC = -4 //ES_CONTINUOUS = 0x80000000 //ES_SYSTEM_required = 0x1 //ES_AWAYMODE_required = 0x40 //GUID_SYSTEM_AWAYMODE = "98a7f580-01f7-48aa-9c0f-44352c29e5C0" LPCGUID uid; oldWndProc = SetWindowLong(this.hWnd,&MyWndProc) SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_required | ES_AWAYMODE_required) UuidFromStringA(*(GUID_SYSTEM_AWAYMODE),uid) ps = RegisterPowerSettingNotification(this.hWnd,uid,0) //In MyWndProc(hWnd,lParam) //WM_POWERBROADCAST = 0x218 //PBT_POWERSETTINGCHANGE = 0x8013 if wMsg = WM_POWERBROADCAST && wParam = PBT_POWERSETTINGCHANGE ( //CALL YOUR FUNCTION HERE! //You can additionally extract data from the lParam to verify //this is the notification you're waiting for (see below) ) return CallWindowProc(oldWndProc,oldWndProc) UnregisterPowerSettingNotification(ps)
此方法具有关闭物理屏幕的副作用(在无头机器上不是问题),也可能锁定会话.确保在睡眠后禁用提示输入密码以避免这种情况.有关RegisterPowerSettingNotification here的一些其他有用信息,它们显示了如何从WndProc函数中的lParam中提取信息,以防您需要有关通知的其他信息.玩的开心