这确实是可能的,但它有点 hackish 并且需要两个完全不同的实现,具体取决于 Windows 版本。对于这两种方法,您都需要在电源选项中设置电源按钮以使计算机进入睡眠状态。
Windows XP 及以下:
您需要覆盖程序主窗口的WndProc 函数。在本机不支持此功能的 IDE 上,可以使用 user32 API 中的SetWindowLong 来完成。在您的自定义 WndProc 函数中,侦听 WM_POWERBROADCAST (0x218) 消息。如果您收到一条 wParam 为 PBT_APMQUERYSUSPEND (0x0) 的消息,请调用您想要的函数,然后返回 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, wMsg, wParam, lParam)
//Before exiting
SetWindowLong(Me.hWnd, GWL_WNDPROC, oldWndProc)
Windows Vista 及更高版本: (感谢 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, GWL_WNDPROC, &MyWndProc)
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED)
UuidFromStringA(*(GUID_SYSTEM_AWAYMODE), uid)
ps = RegisterPowerSettingNotification(this.hWnd, uid, 0)
//In MyWndProc(hWnd, wMsg, wParam, 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, hWnd, wMsg, wParam, lParam)
//Before exiting
SetWindowLong(Me.hWnd, GWL_WNDPROC, oldWndProc)
UnregisterPowerSettingNotification(ps)
此方法的副作用是关闭您的物理屏幕(在无头机器上不是问题),并且还可能锁定您的会话。确保在睡眠后禁用密码提示以避免这种情况。在RegisterPowerSettingNotification 上还有一些其他有用的信息可用here 显示如何从WndProc 函数中的lParam 中提取信息,以防您需要有关通知的更多信息。玩得开心;)