Подтвердить что ты не робот

С# Как получить события, когда экран/дисплей переходит в режим выключения или включения?

Привет, я искал, но я не могу найти ответ. Как узнать, когда экран выключен или включен. Не SystemEvents.PowerModeChanged. Я не знаю, как получить экран/экран СОБЫТИЯ

 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 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 (портативный планшетный ПК). Я хочу, чтобы, когда пользователь перестал работать на время простоя, соединение немедленно закрывается, и когда компьютер возвращается из режима ожидания, он немедленно подключается. Идея Приложение Idle on Code от Tom уже неплохая идея. Чем меньше потребляемая мощность, тем лучше. Запуск должен быть как можно быстрее.

4b9b3361

Ответ 1

Взгляните на этот блог здесь, который поможет вам сделать то, что вы пытаетесь достичь. Кроме того, вам нужно сделать собственное событие, чтобы сделать это для вас примерно так:

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));
   }

}

Изменить: Поскольку 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!");
         }

     }
}

Посмотрев на этот код и понимая, что что-то не совсем правильно, мне стало ясно, что Ману ищет способ опросить систему, чтобы обнаружить статус питания монитора, который недоступен, но код показывает, что программным способом монитор можно включить/выключить/включить, одновременно инициируя событие, но он хотел, чтобы он мог подключиться к WndProc формы и обработать сообщение, указывающее состояние монитора... Теперь, в этот момент, я собираюсь высказать свое мнение по этому поводу.

Я не уверен на 100%, если это можно сделать или Windows действительно отправляет широковещательное сообщение с надписью "Эй! Монитор собирается спать 'или' Эй! Монитор активируется", я боюсь сказать, что мониторы фактически не посылают какой-либо программный сигнал в Windows, чтобы сообщить, что он будет спать/выключен/включен. Теперь, если у кого есть предложения, подсказки, подсказки об этом, не стесняйтесь публиковать свой комментарий...

Программное обеспечение Energy Star как часть вкладки ScreenSaver, которое можно найти при щелчке правой кнопкой мыши на рабочем столе в любом месте, появится всплывающее меню, щелкните левой кнопкой мыши по "Свойствам", появится диалоговое окно "Дисплей" с разными, щелкните левой кнопкой мыши на "ScreenSaver", нажмите кнопку "Power" как часть блока группировки "Monitor Power", эта часть диалогового окна каким-то образом запускает подсистему Windows (драйвер видеокарты? /Energy Star?) для отправьте аппаратный сигнал, чтобы включить функциональность энергосбережения самого монитора... (Мониторы, которые новенькие, не имеют этого по умолчанию AFAIK... не стесняйтесь отклонить это понятие...)

Если не существует документа с недокументированными документами, где-то встроенный и заглубленный глубоко в программном обеспечении Energy-Power (API, безусловно, действительно вызван тем, как нажатие кнопки "Питание" посылает этот сигнал на монитор, в котором режим питания действительно активируйте в результате!), а затем, возможно, запустив поток на фоне указанного приложения формы, опросив, чтобы допросить, что еще неизвестная функциональность или API для проверки состояния питания - должно быть что-то там, о котором знает только Microsoft... в конце концов, Energy Star показала Microsoft, как вызвать режим энергосбережения на самом мониторе, конечно же, это не улица с односторонним движением? или это?

Извините Ману, если я не смог бы помочь дальше....: (

Редактировать # 2: Я подумал о том, что написал ранее в своем редактировании, и немного поработал с корнем для ответа, и я думаю, что придумал ответ, но сначала подумал выскочил в голову, см. этот документ здесь - документ в формате pdf от "terranovum.com", ключ (или так я думал... ) был в реестре, используя последние два раздела реестра на последней странице документа, содержит указанное смещение в количестве секунд и в сочетании с этим CodeProject, чтобы узнать время простоя, было бы легко определить, когда монитор переходит в режим ожидания, звучит просто или так, как я думал, Ману не понравится это понятие....

Дальнейшие исследования с google приводят меня к такому выводу, ответ заключается в расширении спецификации VESA BIOS DPMS (Display Power Management Signaling), теперь возникает вопрос, который возникает из-за этого, как вы допрашиваете эту сигнализацию на биосе VESA, а теперь много современных графических карт что VESA Bios встроен в него, поэтому там должен быть аппаратный порт где-нибудь, где вы можете прочитать значения контактов, используя этот маршрут, потребуется использование InpOut32 или если у вас есть 64-битная Windows, там InpOut64через pinvoke. В принципе, если вы можете вспомнить, используя Turbo C или Turbo Pascal (как 16-бит для DOS), была обычная программа, называемая inport/outport или аналогичная для чтения аппаратного порта, или даже GWBASIC с использованием peek/poke. Если адрес аппаратного порта можно найти, то значения могут быть опрошены, чтобы определить, находится ли монитор в режиме ожидания/выключен/приостановлен/включен, проверяя горизонтальную синхронизацию и вертикальную синхронизацию, это, я думаю, является более надежным решением...

Извиняюсь за длинный ответ, но почувствовал, что мне приходится записывать свои мысли...

Там все еще надеюсь, что Manu:);)

Ответ 2

Недопустимая часть - это то, что я не регистрировался для событий.

Нашел, что есть пример управления питанием от Microsoft:

http://www.microsoft.com/en-us/download/details.aspx?id=4234

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;
}

Ответ 3

/// <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;
    }
}