如何用C#复现Windows内置自动息屏效果 实现可编程息屏功能
两种息屏方案的底层差异
你当前使用的广播WM_SYSCOMMAND消息的方案,和Windows系统原生自动息屏走的是完全不同的执行路径:
- 系统原生息屏由电源管理服务触发,会先更新系统电源状态机,标记显示器进入低功耗模式,此时电源管理服务会持续监听所有用户输入事件,检测到输入后就会主动触发显示器唤醒流程。
- 你用
PostMessage广播消息的方案是直接绕过电源管理状态校验,直接给显示器驱动下发关闭指令,此时电源管理模块依然认为显示器处于正常工作状态,你模拟的用户输入自然不会触发唤醒逻辑,这就是你遇到的唤醒失败的核心原因。
复现原生息屏效果的实现方案
将你的息屏代码改为向桌面窗口同步发送SC_MONITORPOWER指令即可,该路径会触发完整的电源管理状态更新,和系统自动息屏效果完全一致:
[DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); private const uint WM_SYSCOMMAND = 0x0112; private const int SC_MONITORPOWER = 0xF170; private static readonly IntPtr HWND_DESKTOP = IntPtr.Zero; public void TurnOffScreen() { // 同步发送消息到桌面窗口,走标准电源管理流程 SendMessage(HWND_DESKTOP, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)2); }
更稳定的唤醒方案(可选)
不需要模拟鼠标操作,直接调用电源管理API通知系统唤醒显示器即可,不会干扰用户当前的光标状态:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern uint SetThreadExecutionState(uint esFlags); private const uint ES_CONTINUOUS = 0x80000000; private const uint ES_DISPLAY_REQUIRED = 0x00000002; public void TurnOnScreen() { // 通知电源管理需要激活显示器 SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED); // 重置执行状态,不影响后续系统自动息屏逻辑 SetThreadExecutionState(ES_CONTINUOUS); }
内容的提问来源于stack exchange,提问作者MortenMoulder
相关产品推荐
相关产品推荐

