2010-02-05 4 views
12

Hallo Ich habe gesucht, aber ich kann die Antwort nicht finden. Woher weiß ich, wann der Bildschirm aus- oder eingeschaltet wird? Nicht der SystemEvents.PowerModeChanged. Ich weiß nicht, wie die Anzeige/Bildschirm EVENTC# Wie erhalte ich die Ereignisse, wenn der Bildschirm/das Display ausgeschaltet oder eingeschaltet wird?

Vielleicht

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

EDIT abrufen kann ich meine Intension erklären, so gibt es vielleicht eine bessere Lösung. Ich habe einen Dual-Bindungs-WCF-Dienst ausgeführt. Es läuft auf einem Archos (tragbarer Tablet-PC). Ich möchte, dass, wenn der Benutzer für eine Leerlaufzeit aufhörte, die Verbindung sofort geschlossen wird, und wenn der Computer aus dem Leerlauf zurückkehrt, wird er sofort wieder verbunden. Die Idee von Application Idle on Code project von Tom ist schon eine gute Idee. Je weniger Stromverbrauch, desto besser. Der Start muss so schnell wie möglich sein.

Antwort

7

Schauen Sie sich diesen Blog here an, der Ihnen dabei helfen wird, das zu erreichen, was Sie erreichen möchten. Darüber hinaus müssen Sie eine benutzerdefinierte Ereignis machen, dies für Sie tun etwas wie folgt aus:

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: Als Manu nicht sicher war, wie die Ereignisse abzurufen, Bearbeiten gehören eine Probe Code zur Verwendung dieser Klasse wie unten gezeigt.

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

    } 
} 

Nachdem an diesem Code suchen und zu erkennen, dass etwas nicht ganz richtig war, dämmerte es mir, dass Manu nach einem Weg suchte, das System zu befragen den Monitor Energiestatus zu erfassen, die nicht verfügbar ist, aber, Der Code zeigt an, dass der Monitor programmgesteuert ein-/ausgeschaltet werden kann und gleichzeitig ein Ereignis auslöst, aber er wollte, dass er das WndProc eines Formulars einhängen und die Nachricht verarbeiten kann, die den Status des Monitor ... jetzt, an dieser Stelle werde ich meine Meinung dazu äußern.

Ich bin mir nicht 100% sicher, ob das möglich ist, oder sendet Windows tatsächlich eine Broadcast-Nachricht, die etwas wie "Hey! Monitor wird schlafen 'oder' Hey! Der Monitor wird hochgefahren ", ich habe Angst zu sagen, dass Monitore tatsächlich kein Software-Signal an Windows senden, um zu informieren, dass es sich um einen Sleep/Off/On handelt. Nun, wenn jemand eine Vorschläge, Hinweise, Hinweise darüber hat, fühlen Sie sich frei, um Ihren Kommentar zu schreiben ...

Die Energy Star-Software als Teil der ScreenSaver Registerkarte, die gefunden wird, wenn Sie mit der rechten Maustaste auf den Desktop irgendwo, ein Pop - Menü erscheint, Linksklick auf die 'Eigenschaften', ein 'Anzeige' Dialog erscheint, mit verschiedenen Registerkarten, Linksklick auf 'ScreenSaver', Klick auf 'Power' Button als Teil des 'Monitor Power' Gruppierungsfeldes, dieser Teil des Dialogfelds löst irgendwie das Windows-Subsystem (Grafikkarte?/Energy Star-Treiber?) aus, um ein Hardwaresignal zu senden, um die Energiesparfunktion des Monitors selbst einzuschalten ... (Monitore, die neu sind, haben keine dies aktiviert standardmäßig AFAIK ... fühlen Sie sich frei, diesen Begriff zu entlassen ...)

Es sei denn, es ist undocumente d API irgendwo eingebettet und tief in den Energy-Power-Softwaretreiber eingebettet (eine API wird definitiv ausgelöst, wenn das Klicken auf die "Power" -Schaltfläche dieses Signal an den Monitor sendet, in dem der Power-Modus tatsächlich aktiviert wird!) Dann vielleicht, indem Sie einen Thread im Hintergrund der genannten Formularanwendung laufen lassen, Abfragen, um noch, unbekannte Funktionalität oder eine API zu überprüfen, um den Stromstatus zu überprüfen - da muss etwas da sein, dass nur Microsoft weiß ... schließlich Energy Star hat Microsoft gezeigt, wie man den Energiesparmodus auf dem Monitor selbst auslöst, sicherlich ist es keine Einbahnstraße? oder ist es?

Leider Manu, wenn ich nicht weiter helfen könnte .... :(

Edit # 2: ich darüber nachgedacht, was ich früher in der Bearbeitungs schrieb und tat ein bisschen graben um Verwurzelung für eine Antwort und Ich denke, ich kam auf die Antwort, aber zuerst kam mir ein Gedanke in den Sinn, siehe dieses Dokument here - ein pdf-Dokument von 'terranovum.com', der Hinweis (oder so dachte ich ...) war in der Registrierung, Verwenden der letzten zwei Registrierungsschlüssel auf der letzten Seite des Dokuments enthält den angegebenen Offset in die Anzahl der Sekunden, und in Verbindung mit diesem CodeProject Artikel, um die Leerlaufzeit herauszufinden, wäre es einfach zu bestimmen, wann der Monitor in den Standby-Modus versetzt klingt einfach oder so, dachte ich, Manu würde diesen Begriff auch nicht mag ....

Weitere Untersuchungen mit Google zu diesem Schluss führen mich, die Antwort liegt in der Verlängerung der VESA BIOS Spezifikation DPMS (Display Power Management Signaling), jetzt die Frage, die sich daraus ergeben , wie stellst du diese Signalisierung auf dem VESA-Bios ein, jetzt haben viele moderne Grafikkarten, dass VESA Bios eingepasst, so dass es irgendwo einen Hardware-Port geben muss, wo du die Werte der Pins lesen kannst, diese Route verwendend würde erfordern die Verwendung von InpOut32 oder wenn Sie 64bit Windows haben, gibt es eine InpOut64 über pinvoke. Wenn Sie Turbo C oder Turbo Pascal (beide 16bit für DOS) verwenden können, gab es eine Routine namens inport/outport oder ähnlich, um den Hardware-Port zu lesen, oder GWBASIC mit peek/poke. Wenn die Adresse des Hardware-Ports gefunden werden kann, können die Werte abgefragt werden, um festzustellen, ob sich der Monitor im Standby-Modus befindet, ob die horizontale Synchronisation oder die vertikale Synchronisation überprüft wird. Dies ist die zuverlässigere Lösung. ..

Entschuldigung für die lange Antwort, aber fühlte ich meine Gedanken zu schreiben, hatte nach unten ....

Es noch ist Hoffnung da Manu :);)

+1

Nicht wirklich, wie wollen Sie die Ereignisse abrufen. Wie kann ich feststellen, ob das Gerät eingeschaltet oder ausgeschaltet ist? - Nach 10 Minuten dimmt mein Bildschirm. - Nach 15 Minuten geht mein Bildschirm aus. - Ich bewege die Maus, der Bildschirm geht auf ON. Wie bekomme ich diese Ereignisse? (nicht die Sitzungsereignisse) – Manu

+0

@Manu: Lassen Sie mich diese Antwort bearbeiten, um ein Beispiel zu enthalten, wie die Ereignisse abgerufen werden .... – t0mm13b

+0

Wow, interinin. Ich habe nicht gedacht, dass es so kompliziert ist. Ich bin kein Experte, sicherlich nicht mit der Registrierung. Also habe ich ein bisschen Angst davor, mich darauf zu beziehen. "Application Idle" ist bereits eine gute Idee. – Manu

-1
/// <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; 
    } 
} 
+2

Bitte fügen Sie einige Kommentare zu Ihrem Code hinzu (warum dieser Code das Problem löst). Ohne eine Erklärung ist dies keine Antwort. – Artemix

3

der fehlende Teil war, dass ich nicht für die Veranstaltungen registriert.

gefunden, dass ein Power-Management-Beispiel von Microsoft gibt es:

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

Der von Ihnen angegebene Link ist jetzt defekt, und in Ihrem Beispielcode fehlen die Werte für die erste Zeile. Also nur für jeden anderen, der dies in der Zukunft begegnen könnte: Für den GUID_MONITOR_POWER_ON Wert (02731015-4510-4526-99e6-e5a17ebd1aea) habe ich [diesen Link] benutzt (https://msdn.microsoft.com/en-us/ Bibliothek/Windows/Desktop/hh448380 (v = vs.85) .aspx) als Referenz und 0 für den Wert von DEVICE_NOTIFY_WINDOW_HANDLE. –