c# Как получить события, когда экран / дисплей выключается или включается?
Привет я искал, но я не могу найти ответ. Как я узнаю, когда экран выключается или включается. Не 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'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 (портативный планшетный ПК). Я хочу, чтобы когда пользователь перестал работать на холостом ходу время, соединение закрывается немедленно,и когда компьютер возвращается из простоя, он немедленно подключается. Идея приложение простаивает в проекте кода от Тома уже хорошая идея. Чем меньше потребляемая мощность , тем лучше. Запуск должен быть максимально быстрым.
3 ответов
посмотрите на этот блог здесь который поможет вам сделать то, что вы пытаетесь достичь. Кроме того, вы должны принять пользовательское событие, чтобы сделать это для вас что-то вроде этого:
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: As Ману не был уверен, как получить события, это редактирование будет включать пример кода о том, как использовать этот класс, как показано ниже.
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 как часть вкладки заставки, которая находится при щелчке правой кнопкой мыши на рабочем столе в любом месте появляется всплывающее меню, щелчок левой кнопкой мыши по "свойствам", появляется диалоговое окно "дисплей" с разными страницами вкладок, щелчок левой кнопкой мыши по "заставке", Нажмите кнопку "Питание" как часть окна группировки "монитор питания", эта часть диалогового окна, каким-то образом запускает подсистему Windows (видеокарта?/ Драйвер Energy Star?) для отправки аппаратного сигнала для включения функции энергосбережения самого монитора...(Мониторы, которые являются совершенно новыми, не имеют этого по умолчанию AFAIK...чувствовать свободен отвергнуть это понятие...)
Если нет недокументированного API где-то встроенного и похороненного глубоко в драйвере программного обеспечения Energy-Power (API, безусловно, действительно срабатывает относительно того, как нажатие на кнопку "Power" отправляет этот сигнал на монитор, в котором режим питания действительно активируется в результате!) затем, возможно, запустив поток в фоновом режиме указанного приложения формы, опрос, чтобы опросить, что еще неизвестная функциональность или API для проверки статус питания-там должно быть что-то, о чем знает только Microsoft...ведь Energy Star показала Microsoft, как запустить режим энергосбережения на самом мониторе, ведь это не улица с односторонним движением? или нет?
извините ману, если я не мог помочь дальше .... :(
Edit #2: Я подумал о том, что я написал ранее в редактировании и немного покопался в поисках ответа, и я думаю, что я придумал ответ, но сначала подумал выскочил в голову, смотри этот документ здесь - документ pdf из 'terranovum.com - ... ключ (по крайней мере, я так думал...) был в реестре, используя последние два раздела реестра на последней странице документа, содержит указанное смещение на количество секунд, и в сочетании с этим CodeProject статья, чтобы узнать время простоя, было бы легко определить, когда монитор переходит в режим ожидания, звучит просто или так я думал, Ману не понравится это понятие любой....
дальнейшие исследования с google приводят меня к этому выводу, ответ заключается в расширении VESA BIOS спецификация DPMS (Display Power Management Signalling), теперь вопрос, который возникает из этого, заключается в том, как вы допрашиваете эту сигнализацию на VESA bios, теперь у многих современных видеокарт есть этот VESA Bios, поэтому где-то должен быть аппаратный порт, где вы можете прочитать значения контактов, используя этот маршрут потребует использования InpOut32 или если у вас 64-битная система Windows, есть InpOut64 via pinvoke. В основном, если вы можете вспомнить использование Turbo C или Turbo Pascal (оба 16bit для DOS), была процедура под названием inport/outport или аналогичная для чтения аппаратного порта или даже GWBASIC с помощью peek/poke. Если адрес аппаратного порта может быть найден, то значения могут быть опрошены, чтобы определить, находится ли монитор в режиме ожидания / выключен / приостановлен / включен проверка горизонтальной синхронизации и вертикальной синхронизации, я думаю, является более надежным решением...
извиняюсь за длинный ответ, но чувствовал, что должен записать свои мысли....
есть еще надежда там Ману:);)
недостающая часть заключалась в том, что я не регистрировался для событий.
обнаружили, что есть пример управления питанием от 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;
}
/// <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;
}
}