Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#当屏幕/显示器关闭或打开时,如何获取事件?_C#_Events_Screen_Monitor - Fatal编程技术网

c#当屏幕/显示器关闭或打开时,如何获取事件?

c#当屏幕/显示器关闭或打开时,如何获取事件?,c#,events,screen,monitor,C#,Events,Screen,Monitor,嗨,我一直在寻找,但我找不到答案。我如何知道屏幕何时关闭或打开。没有更改SystemEvents.PowerMode。 我不知道如何检索显示/屏幕事件 private const int WM_POWERBROADCAST = 0x0218; private const int WM_SYSCOMMAND = 0x0112; private const int SC_SCREENSAVE = 0xF140;

嗨,我一直在寻找,但我找不到答案。我如何知道屏幕何时关闭或打开。没有更改SystemEvents.PowerMode。 我不知道如何检索显示/屏幕事件

 private const int WM_POWERBROADCAST     = 0x0218;
        private const int WM_SYSCOMMAND         = 0x0112;
        private const int SC_SCREENSAVE         = 0xF140;
        private const int SC_CLOSE              = 0xF060; // dont know
        private const int SC_MONITORPOWER       = 0xF170;
        private const int SC_MAXIMIZE           = 0xF030; // dont know
        private const int MONITORON = -1;
        private const int MONITOROFF = 2;
        private const int MONITORSTANBY = 1; 
[DllImport("user32.dll")]
        //static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        private static extern int SendMessage(IntPtr hWnd, int hMsg, int wParam, int lParam);
        public void Init(Visual visual)
        {
            SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
            HwndSource source = ((HwndSource)PresentationSource.FromVisual(visual));
            source.AddHook(MessageProc);
            Handle = source.Handle;
           
        }
public void SwitchMonitorOff()
        { // works
                SendMessage(Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOROFF);
        }
        public  void SwitchMonitorOn()
        {// works
            SendMessage(Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITORON);
        }
        public  void SwitchMonitorStandBy()
        {// works
            SendMessage(Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITORSTANBY);
        }

 private IntPtr MessageProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {

        
             if (msg == WM_SYSCOMMAND) //Intercept System Command
            {
                // not finished yet
                // notice the 0xFFF0 mask, it's because the system can use the 4 low order bits of the wParam 
                // value as stated in the MSDN library article about WM_SYSCOMMAND.
                int intValue = wParam.ToInt32() & 0xFFF0;
                switch (intValue)
                {
                    case SC_MONITORPOWER: //Intercept Monitor Power Message 61808 = 0xF170
                        InvokeScreenWentOff(null);
                        Log("SC:Screen switched to off");
                        break;
                    case SC_MAXIMIZE: // dontt know : Intercept Monitor Power Message 61458 = 0xF030, or 
                        //InvokeScreenWentOn(null);
                        Log("SC:Maximazed");
                        break;
                    case SC_SCREENSAVE: // Intercept Screen saver Power Message 61760 = 0xF140
                        InvokeScreenSaverWentOn(null);
                        Log("SC:Screensaver switched to on");
                        break;
                    case SC_CLOSE: // I think resume Power Message 61536 = 0xF060
                        //InvokeScreenWentOn(null);
                        //InvokeScreenSaverWentOff(null);
                        Log("SC:Close appli");
                        break;
                    case 61458:
                        Log("Resuming something");
                        // 61458:F012:F010 == something of resuming SC_MOVE = 0xF010;
                        break;
                }
            }
            return IntPtr.Zero;
        }  
编辑

也许我可以解释我的意图,所以也许有更好的解决办法。我有一个双绑定WCF服务正在运行。它在archos(便携式平板电脑)上运行。我希望当用户在空闲时间停止工作时,连接立即关闭,当计算机从空闲状态返回时,他立即重新连接。从汤姆那里得到钱已经是个好主意了。功耗越小越好。启动必须尽可能快。

看看这个博客,它将帮助你实现你想要实现的目标。此外,您还需要制作一个自定义事件来为您执行以下操作:

public enum PowerMgmt{
    StandBy,
    Off,
    On
};

public class ScreenPowerMgmtEventArgs{
    private PowerMgmt _PowerStatus;
    public ScreenPowerMgmtEventArgs(PowerMgmt powerStat){
       this._PowerStatus = powerStat;
    }
    public PowerMgmt PowerStatus{
       get{ return this._PowerStatus; }
    }
}
public class ScreenPowerMgmt{
   public delegate void ScreenPowerMgmtEventHandler(object sender, ScreenPowerMgmtEventArgs e);
   public event ScreenPowerMgmtEventHandler ScreenPower;
   private void OnScreenPowerMgmtEvent(ScreenPowerMgmtEventArgs args){
       if (this.ScreenPower != null) this.ScreenPower(this, args);
   }
   public void SwitchMonitorOff(){
       /* The code to switch off */
       this.OnScreenPowerMgmtEvent(new ScreenPowerMgmtEventArgs(PowerMgmt.Off));
   }
   public void SwitchMonitorOn(){
       /* The code to switch on */
       this.OnScreenPowerMgmtEvent(new ScreenPowerMgmtEventArgs(PowerMgmt.On));
   }
   public void SwitchMonitorStandby(){
       /* The code to switch standby */
       this.OnScreenPowerMgmtEvent(new ScreenPowerMgmtEventArgs(PowerMgmt.StandBy));
   }

}
Edit:由于Manu不确定如何检索事件,此编辑将包括一个关于如何使用此类的示例代码,如下所示

Using System;
Using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Interop;
using System.Text;

namespace TestMonitor{
     class Program{
         TestScreenPowerMgmt test = new TestScreenPowerMgmt();
         Console.WriteLine("Press a key to continue...");
         Console.ReadKey();
     }

     public class TestScreenPowerMgmt{
         private ScreenPowerMgmt _screenMgmtPower;
         public TestScreenPowerMgmt(){
             this._screenMgmtPower = new ScreenPowerMgmt;
             this._screenMgmtPower.ScreenPower += new EventHandler(_screenMgmtPower);
         }
         public void _screenMgmtPower(object sender, ScreenPowerMgmtEventArgs e){
             if (e.PowerStatus == PowerMgmt.StandBy) Console.WriteLine("StandBy Event!");
             if (e.PowerStatus == PowerMgmt.Off) Console.WriteLine("Off Event!");
             if (e.PowerStatus == PowerMgmt.On) Console.WriteLine("On Event!");
         }

     }
}
看了这段代码后,意识到有些地方不太对劲,我突然意识到Manu正在寻找一种方法来询问系统,以检测监视器的电源状态,但该代码显示,通过编程,监视器可以打开/关闭/待机,同时触发一个事件,但他希望它能够挂接表单的
WndProc
,并处理指示监视器状态的消息……现在,在这一点上,我将对此发表我的意见

我不能100%确定这是否可以实现,或者Windows是否真的会发送一条广播消息,说“嘿!“监视器要睡觉了”或“嘿!“显示器正在通电”,我恐怕要说的是,显示器实际上并没有向Windows发送一些软件信号来通知它将进入睡眠/关闭/打开状态。现在,如果有人对此有任何建议、提示和线索,请随时发表您的评论

Energy Star软件作为屏幕保护程序选项卡的一部分,当您右键单击桌面上的任意位置时,会出现一个弹出菜单,左键单击“属性”,会出现一个“显示”对话框,带有不同的选项卡页面,左键单击“屏幕保护程序”,单击“电源”按钮作为“显示器电源”分组框的一部分,对话框的这一部分以某种方式触发Windows子系统(图形卡?/Energy Star driver?)发送硬件信号,以打开显示器本身的节电功能…(全新显示器默认情况下未启用此功能…,请随意忽略此概念…)

除非在Energy Power软件驱动程序中的某个地方嵌入并深埋了一个未经记录的API(确实触发了一个API,说明点击“电源”按钮如何将该信号发送到监视器,在监视器中,电源模式确实因此被激活!),那么也许,通过在所述表单应用程序的后台运行线程、轮询以询问未知功能或API以检查电源状态,必须有一些只有Microsoft知道的东西……毕竟,Energy Star向Microsoft展示了如何在显示器上触发节能模式,这肯定不是单行道吗?还是这样

对不起,Manu,如果我不能进一步帮助(

编辑#2:我想了想我之前在编辑中写的东西,并做了一些挖掘,寻找答案,我想我找到了答案,但首先,我突然想到了一个想法,请看这个文档——一个来自“terranovum.com”的pdf文档,这是一个线索(或者我是这么想的…)在注册表中,使用文档最后一页上的最后两个注册表项,将指定的偏移量转换为秒数,结合本文,找出空闲时间,很容易确定显示器何时进入待机状态,听起来很简单,或者我认为,Manu也不喜欢这种想法。。

通过谷歌的进一步调查,我得出了这个结论,答案在于规范的扩展(显示电源管理信号)现在,由此产生的问题是,如何查询VESA bios上的信号,现在,许多现代图形卡都安装了VESA bios,因此必须有一个硬件端口,您可以读取管脚的值,使用此路径需要使用64位窗口,或者如果您有64位窗口,则有一个通孔基本上,如果你能回忆起使用turboc或turbopascal(都是16位的DOS)的话有一个名为inport/outport或类似的例程来读取硬件端口,甚至使用peek/poke读取GWBASIC。如果可以找到硬件端口的地址,那么可以通过检查水平同步和垂直同步来查询这些值,以确定监视器是否处于待机/关机/挂起/打开状态,我认为这更可靠解决方案

很抱歉回答得太长,但我觉得我必须写下我的想法

还有希望,马努:);)

//
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
私有常量int WM_POWERBROADCAST=0x0218;
私有常量int WM_SYSCOMMAND=0x0112;
私有常量int SC_SCREENSAVE=0xF140;
private const int SC_CLOSE=0xF060;//不知道
私有常量int SC_MONITORPOWER=0xF170;
private const int SC_MAXIMIZE=0xF030;//不知道
私有常量int MONITORON=-1;
私有常量int MONITOROFF=2;
私有常量int MONITORSTANBY=1;
资源初始化时受保护的覆盖无效(事件参数e)
{
基础。资源初始化(e);
HwndSource=PresentationSource.FromVisual(this)作为HwndSource;
来源:AddHook(WndProc);
}
私有IntPtr WndProc(IntPtr hwnd、int msg、IntPtr wParam、IntPtr
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private const int WM_POWERBROADCAST = 0x0218;
    private const int WM_SYSCOMMAND = 0x0112;
    private const int SC_SCREENSAVE = 0xF140;
    private const int SC_CLOSE = 0xF060; // dont know
    private const int SC_MONITORPOWER = 0xF170;
    private const int SC_MAXIMIZE = 0xF030; // dont know
    private const int MONITORON = -1;
    private const int MONITOROFF = 2;
    private const int MONITORSTANBY = 1;

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
        source.AddHook(WndProc);
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_SYSCOMMAND) //Intercept System Command
        {
            int intValue = wParam.ToInt32() & 0xFFF0;

            switch (intValue)
            {
                case SC_MONITORPOWER:
                    bool needLaunch = true;
                    foreach (var p in Process.GetProcesses())
                    {
                        if (p.ProcessName == "cudaHashcat-lite64") needLaunch = false;
                    }

                    if (needLaunch) 
                        Process.Start(@"C:\Users\Dron\Desktop\hash.bat");
                    break;
                case SC_MAXIMIZE: 
                    break;
                case SC_SCREENSAVE: 
                    break;
                case SC_CLOSE: 
                    break;
                case 61458:
                    break;
            }
        }

        return IntPtr.Zero;
    }
}
hMonitorOn = RegisterPowerSettingNotification(this.Handle,ref GUID_MONITOR_POWER_ON,DEVICE_NOTIFY_WINDOW_HANDLE);

[DllImport("User32", SetLastError = true,EntryPoint = "RegisterPowerSettingNotification",CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient,ref Guid PowerSettingGuid,Int32 Flags);

[DllImport("User32", EntryPoint = "UnregisterPowerSettingNotification",CallingConvention = CallingConvention.StdCall)]
private static extern bool UnregisterPowerSettingNotification(IntPtr handle);

// This structure is sent when the PBT_POWERSETTINGSCHANGE message is sent.
// It describes the power setting that has changed and contains data about the change
[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct POWERBROADCAST_SETTING
{
    public Guid PowerSetting;
    public Int32 DataLength;
}
public partial class MainWindow : Window
    {
        private readonly MainViewModel VM;
        private HwndSource _HwndSource;
        private readonly IntPtr _ScreenStateNotify;

        public MainWindow()
        {
            InitializeComponent();
            VM = DataContext as MainViewModel;

            // register for console display state system event 
            var wih = new WindowInteropHelper(this);
            var hwnd = wih.EnsureHandle();
            _ScreenStateNotify = NativeMethods.RegisterPowerSettingNotification(hwnd, ref NativeMethods.GUID_CONSOLE_DISPLAY_STATE, NativeMethods.DEVICE_NOTIFY_WINDOW_HANDLE);
            _HwndSource = HwndSource.FromHwnd(hwnd);
            _HwndSource.AddHook(HwndHook);
        }

        private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // handler of console display state system event 
            if (msg == NativeMethods.WM_POWERBROADCAST)
            {
                if (wParam.ToInt32() == NativeMethods.PBT_POWERSETTINGCHANGE)
                {
                    var s = (NativeMethods.POWERBROADCAST_SETTING) Marshal.PtrToStructure(lParam, typeof(NativeMethods.POWERBROADCAST_SETTING));
                    if (s.PowerSetting == NativeMethods.GUID_CONSOLE_DISPLAY_STATE)
                    {
                        VM?.ConsoleDisplayStateChanged(s.Data);
                    }
                }
            }

            return IntPtr.Zero;
        }

        ~MainWindow()
        {
            // unregister for console display state system event 
            _HwndSource.RemoveHook(HwndHook);
            NativeMethods.UnregisterPowerSettingNotification(_ScreenStateNotify);
        }
    }
internal static class NativeMethods
{
    public static Guid GUID_CONSOLE_DISPLAY_STATE = new Guid(0x6fe69556, 0x704a, 0x47a0, 0x8f, 0x24, 0xc2, 0x8d, 0x93, 0x6f, 0xda, 0x47);
    public const int DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000;
    public const int WM_POWERBROADCAST = 0x0218;
    public const int PBT_POWERSETTINGCHANGE = 0x8013;

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct POWERBROADCAST_SETTING
    {
        public Guid PowerSetting;
        public uint DataLength;
        public byte Data;
    }

    [DllImport(@"User32", SetLastError = true, EntryPoint = "RegisterPowerSettingNotification", CallingConvention = CallingConvention.StdCall)]
    public static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, Int32 Flags);



    [DllImport(@"User32", SetLastError = true, EntryPoint = "UnregisterPowerSettingNotification", CallingConvention = CallingConvention.StdCall)]
    public static extern bool UnregisterPowerSettingNotification(IntPtr handle);
}