这确实是可能的,但它有点骇人听闻,并且需要两个完全不同的实现,具体取决于 Windows 版本。对于这两种方法,您都需要在电源选项中设置电源按钮以使计算机进入睡眠状态。
Windows XP 及以下:
您需要覆盖程序主窗口的WndProc
功能。在本机不支持此功能的 IDE 上,可以使用SetWindowLong
user32 API 来完成。在您的自定义WndProc
函数中,收听一条WM_POWERBROADCAST (0x218)
消息。如果您收到 wParam of 的消息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 让我走上正轨)
您需要WndProc
像 XP 一样覆盖,但还需要调用SetThreadExecutionState
kernel32 API 来禁用睡眠模式,并调用RegisterPowerSettingNotification
user32 API 来监听高级电源通知。您将特别收听GUID_SYSTEM_AWAYMODE
通知,该通知在系统被要求进入睡眠状态但无法进入睡眠状态时发出。要轻松地将字符串转换为正确格式,LPCGUID
您可以UuidFromStringA
在 rpcrt4.dll API 中使用。示例代码:
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
提供了一些其他有用的信息,显示了如何从函数中提取信息,以防您需要有关通知的其他信息。玩得开心 ;)lParam
WndProc