如何在Windows 11现代待机模式下用C#的SendMessage关闭显示器
解决Modern Standby下SendMessage关闭显示器失效问题
原来通过SendMessage(handle, 0x112, 0xF170, 2);仅关闭显示器的方法,在Modern Standby(S0低功耗待机)环境下会触发系统睡眠而非仅关屏,这是因为新的电源管理逻辑改变了WM_SYSCOMMAND(0x112)搭配SC_MONITORPOWER(0xF170)参数的行为。以下是几种可行的替代实现方式:
方案1:结合SetThreadExecutionState阻止系统睡眠
通过临时设置系统执行状态,确保发送关屏消息时系统不会进入睡眠:
#include <windows.h> // 临时保持系统运行状态,阻止睡眠 DWORD prevExecutionState = SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); // 广播关闭显示器消息(使用HWND_BROADCAST确保所有窗口接收) SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2); // 恢复之前的系统执行状态(可选,根据业务需求决定是否保留阻止状态) SetThreadExecutionState(prevExecutionState);
ES_SYSTEM_REQUIRED标记会让系统保持活跃,避免触发S0待机;- 使用
HWND_BROADCAST替代特定窗口句柄,更贴合系统自动关屏的触发逻辑。
方案2:使用PowerCreateRequest API设置电源请求
通过创建电源请求临时阻止系统睡眠,再执行关屏操作:
#include <windows.h> #include <powrprof.h> #pragma comment(lib, "powrprof.lib") // 定义电源请求上下文 POWER_REQUEST_CONTEXT powerContext = {0}; powerContext.Version = POWER_REQUEST_CONTEXT_VERSION; powerContext.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING; powerContext.Reason.SimpleReasonString = L"临时阻止睡眠以关闭显示器"; // 创建电源请求句柄 HANDLE hPowerRequest = PowerCreateRequest(&powerContext); if (hPowerRequest != NULL) { // 设置系统保持运行的请求 PowerSetRequest(hPowerRequest, PowerRequestSystemRequired); // 发送关屏消息 SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2); // 短暂延迟确保显示器关闭,再释放请求 Sleep(1000); PowerClearRequest(hPowerRequest, PowerRequestSystemRequired); CloseHandle(hPowerRequest); }
这种方式更符合Modern Standby的电源管理规范,避免强制修改系统状态带来的潜在问题。
方案3:直接模拟系统自动关屏的触发逻辑
系统本身能正常执行1分钟关屏、15分钟睡眠的逻辑,说明可以通过调用系统内部的电源管理接口实现。可以使用CallNtPowerInformation API触发显示器关闭:
#include <windows.h> #include <powrprof.h> #pragma comment(lib, "powrprof.lib") SYSTEM_POWER_STATE powerState = PowerMonitorOff; CallNtPowerInformation(SetSystemPowerState, &powerState, sizeof(powerState), NULL, 0);
注意:部分系统可能需要管理员权限才能调用该API。
内容的提问来源于stack exchange,提问作者Seth
相关产品推荐
相关产品推荐

