You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 01:45:03