打开/关闭监视器

Posted

技术标签:

【中文标题】打开/关闭监视器【英文标题】:Turn on/off monitor 【发布时间】:2010-10-17 08:14:08 【问题描述】:

是否可以通过代码 (C#) 以编程方式?

【问题讨论】:

在您的问题中添加“以编程方式”可能会使您免于被否决。我的 2 美分 :-) 同意上述观点:虽然这没有赢得“好问题”奖,但我个人不同意这么多反对意见。这实际上是一个有效的问题。 每个人都认为他们比 OP 更聪明并且知道他/她的问题。 Vinoth 没有问如何使用按钮,他/她问是否可以使用代码... 这是来自 Vinoth 的一个非常典型的问题,尽管反复的 cmets 和有用的提示促使他提出更好的问题,但他仍然提出了问得不好的模棱两可的问题。 @Binary,我不同意你的看法。这不是拖钓,您可以回答问题,而不是试图对这个简单的问题投反对票。 【参考方案1】:

你试过用谷歌搜索吗?

第一击: http://www.codeproject.com/KB/cs/Monitor_management_guide.aspx

我并不奇怪您需要使用 Windows 提供的一些 DLL。

(我猜你需要一个 C# 解决方案,因为这是你应用的唯一标签)。

2013 年 2 月 8 日编辑:

有人提到该解决方案在 Windows 7 en 8 下不再有效。好吧,这是一个在 Windows 7 下运行良好的解决方案,尚未尝试 Windows 8。

http://cocoa.ninja/posts/Turn-off-your-monitor-in-Csharp.html

namespace MonitorOff 

    public enum MonitorState 
        MonitorStateOn = -1,
        MonitorStateOff = 2,
        MonitorStateStandBy = 1
    

    public partial class Form1 : Form 
        [DllImport("user32.dll")]
        private static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);

        public Form1() 
            InitializeComponent();
            SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
        

        void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e) 
            SetMonitorInState(MonitorState.MonitorStateOff);
        

        private void button1_Click(object sender, EventArgs e) 
            SetMonitorInState(MonitorState.MonitorStateOff);
        

        private void SetMonitorInState(MonitorState state) 
            SendMessage(0xFFFF, 0x112, 0xF170, (int)state);
        
    

【讨论】:

你知道这个答案是在2009年给出的吗? 我愿意,但由于 2013 年答案在 Google 中的排名仍然很高,我想像我这样的其他人会出现,看到这个,然后去下载并尝试这个项目,却发现它不起作用在 2009 年后的 Windows 操作系统中。我试图为他们节省 10 多分钟的时间。我绝不想剥夺您的回答所增加的价值,我相信它帮助了成千上万的人,我只是想让人们知道有些事情发生了变化。 第二个链接现已断开。 也看到这个类似的答案:***.com/a/42393472/1468842 在 win 10 中,这会使所有显示器进入“睡眠”状态,直到我移动鼠标。【参考方案2】:

按下开/关按钮


如果您想在代码中执行此操作,显然这在 Win32 API 中是可能的:

SendMessage hWnd、WM_SYSCOMMAND、SC_MONITORPOWER、参数

其中 WM_SYSCOMMAND = 0x112 和 SC_MONITORPOWER = 0xF170 和 param 指示将监视器置于的模式: -1:开 2:关闭 1:节能模式

hWnd 可以是任何窗口的句柄 - 所以如果你有一个表单,这样的东西应该可以工作

int WM_SYSCOMMAND = 0x112;
int SC_MONITORPOWER = 0xF170;

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

public static void Main(string[] args)

    Form f = new Form();
    bool turnOff = true;   //set true if you want to turn off, false if on
    SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)(turnOff ? 2 : -1));

请注意,我实际上并没有尝试过这个......

【讨论】:

如果停电,可能因为太暗而看不到开/关按钮,因此您可能需要手电筒来应对这种情况。 我很想回答这个问题,+1 :-) 关闭显示器效果很好,但我似乎无法将其打开。 关闭显示器 off 在 Windows 10 中有效,但是尝试再次打开它会导致短暂打开(大约一秒钟),然后再次黑屏。 如果连接了两台显示器,是否可以打开/关闭第一台和第二台显示器?【参考方案3】:

上面的答案https://***.com/a/713504/636189 非常适合关闭 Windows 7/8 显示器,但不适用于唤醒它。在这些系统上,你需要做一些像这样的黑客行为(如 https://***.com/a/14171736/636189 所示):

[DllImport("user32.dll")]
static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo);

private const int MOUSEEVENTF_MOVE = 0x0001;

private void Wake()
mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, UIntPtr.Zero);
Sleep(40);
mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, UIntPtr.Zero);

【讨论】:

此解决方案在带有两个显示器的 Windows Vista 上运行良好。 只需 2 美分,mouse_event 无法使 MS office Communicator 保持“活动”状态,只有鼠标单击和 keybd_event,因此实际使用这些或移动鼠标可能是未来的证明超过一个像素,以防有人认为,“当有人撞到他们的桌子时,我们应该停止打开显示器。” 上面接受的答案在 Windows 10 上对我不起作用。接受的答案会短暂打开屏幕,但随后又会关闭。这是在 Surface Pro 上。一旦我实施了这个解决方案,它就工作得很好。是的,是的,但它很有效,对我约会的女孩来说已经足够了! 如果您在这里寻找一种在 .bat 文件或任务计划程序操作(例如)中执行此操作的方法,而不是从 C# 中执行此操作,那么这个答案:superuser.com/a/1371383 建议一种方法。您可以使用以下命令触发 40 像素的水平鼠标移动,如果由于不活动而关闭,将重新打开显示:powershell (Add-Type '[DllImport(\"user32.dll\")]^public static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, int dwExtraInfo);' -Name user32 -PassThru)::mouse_event(1,40,0,0,0)【参考方案4】:

对于希望在控制台应用程序上使用此功能的人:

using System;
using System.Runtime.InteropServices;
using System.Timers;

namespace TurnScreenOFF

    class Program
    
        private static int WM_SYSCOMMAND = 0x0112;
        private static uint SC_MONITORPOWER = 0xF170;

        public static void Main(string[] args)
        
            SendMessage(GetConsoleWindow(), WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)2);
        

        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
    

经过调整和测试。 100% 在 Windows 8 上工作。

【讨论】:

不需要调用GetConsoleWindow,也不需要在非控制台应用程序上获取GUI hwnd,只需使用HWND_BROADCAST消息代替(SendMessage(New IntPtr(0xFFFF)...)。 适用于 Windows 10 家庭版,使用 HWND_BROADCASTPostMessage() HWND_BROADCAST 在 Windows 10 上为我工作并锁定,不知道为什么,可能是我拥有的多个显示器。 GetConsoleWindow() 虽然有效。【参考方案5】:

此代码可用于打开和关闭。它也适用于 Windows 7。

   private int SC_MONITORPOWER = 0xF170;

    private uint WM_SYSCOMMAND = 0x0112;

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);



    enum MonitorState
    
        ON = -1,
        OFF = 2,
        STANDBY = 1
    
    private void SetMonitorState(MonitorState state)
    
        Form frm = new Form();

        SendMessage(frm.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)state);

    

要调用该函数,您必须这样做:

SetMonitorState(MonitorState.ON);

SetMonitorState(MonitorState.OFF);

注意:此代码在 WPF 应用程序中测试。使用以下命名空间:

using System.Runtime.InteropServices;
using System.Windows.Forms;

【讨论】:

【参考方案6】:

我找不到复制粘贴示例,所以自己创建了一个,别忘了添加对 System.Windows.Forms 的引用。

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;


namespace monitor_on_off

    class Program
    
        [DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll")]
        static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo);

        private const int WmSyscommand = 0x0112;
        private const int ScMonitorpower = 0xF170;
        private const int MonitorShutoff = 2;
        private const int MouseeventfMove = 0x0001;

        public static void MonitorOff(IntPtr handle)
        
            SendMessage(handle, WmSyscommand, (IntPtr)ScMonitorpower, (IntPtr)MonitorShutoff);
        

        private static void MonitorOn()
        
            mouse_event(MouseeventfMove, 0, 1, 0, UIntPtr.Zero);
            Thread.Sleep(40);
            mouse_event(MouseeventfMove, 0, -1, 0, UIntPtr.Zero);
        

        static void Main()
        
            var form = new Form();

            while (true)
            
                MonitorOff(form.Handle);
                Thread.Sleep(5000);
                MonitorOn();
                Thread.Sleep(5000);
            
        
    

【讨论】:

在 windows 10 64 位上为我工作。甚至创建了一个使用它的小型 nodejs 服务器,现在我可以从我的手机上关闭屏幕。非常感谢。顺便说一句,打开也有效,但如果我再次运行关闭命令,即使它已关闭它也会打开。对我来说并不重要【参考方案7】:

我已经完成了每个人发布的让显示器进入睡眠状态并稍后在其他时间唤醒它的每一种方法。当然SendMessage() 确实适用于 Windows XP,但在显示器休眠一段时间后它不会唤醒显示器。我尝试过使用 C#、DOS、用于玩电源配置文件的脚本和 Powershell。最终我放弃了,回到了起点,我的第一个想法被证明是正确的。你需要在显示器关闭后使用PostMessage(),更好的是,你应该总是使用PostMessage()


所以你之前看到的所有代码都是正确的,改为使用以下代码:

using System.Runtime.InteropServices;
[DllImport("user32.dll")]
static extern IntPtr PostMessage(int hWnd, int msg, int wParam, int lParam);
PostMessage(-1, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_OFF);

此时执行和正常工作(2015 年 5 月 11 日)我正在跑步

Windows 7 专业版 6.1.7601 Service Pack 1 Build 7601 Visual Studio Professional 2013 版本 12.0.31101.00 更新 4 .NET Framework 4.5.51209 C#

我的系统完全是最新的。

【讨论】:

嗨@Mike,我试过你的解决方案,我的显示器变黑了,但大约1秒后它们又亮了。尝试使用 PostMessage 和 SendMessage。 (Windows 7 6.1.7601 x64)有什么想法吗?【参考方案8】:

SLOC最少的答案:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

static class Program

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

    [STAThread]
    static void Main()
    
        SendMessage(new Form().Handle, 0x0112, 0xF170, 2);
    

【讨论】:

恕我直言,并不比 2011 年 klaasjan69 的答案好。它更短,但可读性更低。它只回答“关闭”的情况,而不回答“打开”的情况。我不认为“最少 SLOC”是一种优势。【参考方案9】:

对于 Windows 10(在 Pro 64 位上测试),我能够使用本页中提到的 SendMessage() 技术关闭显示器。 但是,我无法重新打开显示器:“鼠标移动”技巧不起作用,SendMessage() 技术会将屏幕重新打开一秒钟然后关闭,使用 PostMessage() 并没有改变任何东西。

但诀窍其实很简单,我所要做的就是用SendKeys() 模拟按键。我在这里使用 ALT 是因为它本身对系统没有影响,但它可以是任何其他键。

SendKeys.SendWait("%");

如果您不使用 Windows.Forms,发送“ALT”也可以使用 SendInput(),但实现时间较长。

【讨论】:

以上是关于打开/关闭监视器的主要内容,如果未能解决你的问题,请参考以下文章

怎么样结束关闭linux/ubuntu系统中的进程

为啥打开arduino串口监视器后软串口才能向其他元件收发数据

arduino 使用 pySerial 打开/关闭 LED

Mac 打开任务管理器 关闭程序

某个虚拟机卡死时,单独关闭卡死虚拟机的方法

屏幕打开/关闭时如何更新 Android 小部件?