2012-06-05 10 views
6

Ho fatto uno screensaver in .Net 4.0. Fondamentalmente sposta semplicemente i bit in un'immagine attorno e li mostra usando. Invalidate su un timer e sovrascrivendo l'evento onPaint.Il mio salvaschermo interrompe la sospensione dello schermo ma non lo voglio

Finora funziona benissimo, tuttavia, ho notato un problema.

Arresta il monitor dalla sospensione dopo il timeout di sospensione. Da quando l'ho installato, il mio monitor rimane attivo 24/7 ora.

Il fatto è che non ho fatto nulla per arrestare in modo specifico le funzioni di risparmio energetico - e mi sono assicurato che le impostazioni di risparmio energetico del mio computer fossero impostate (sono). Quindi ho scelto un altro salvaschermo solo per essere sicuro che le impostazioni funzionassero ancora. Il monitor è sospeso dopo il timeout.

Cosa devo fare per giocare bene con il risparmio energia? Ho cercato questa risposta su Google e tutto ciò che ho trovato è come bloccare la gestione dell'alimentazione e non l'ho bloccato esplicitamente! Voglio solo che la sospensione sia permessa quando è il momento.

risposta

1

Sono stato in grado di ottenere il mio programma per "giocare bene". Non so perché funzioni e il codice originale no, ma questo non solo funziona, ma rende il programma più "risparmio energetico" perché riduce i cicli della CPU non eseguendo calcoli dopo la sospensione dello schermo. In breve, visualizzo un'anteprima dei messaggi WndProc e cerco che il monitor venga sospeso e una volta ricevuto, interrompo il ridisegno finché non riprende (è possibile riprendere e mantenere attivo lo screensaver).

modifiche codice:

// Field Definitions 
    /// <summary> 
    /// Constants that relate to the WndProc messages we wish to intercept and evaluate. 
    /// </summary> 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Standard practice to use this naming style for Win32 API Constants.")] 
    private const int WM_SYSCOMMAND = 0x0112, SC_MONITORPOWER = 0xF170; 

    /// <summary> 
    /// Gets or sets whether we are suspended. Should coincide with whether the display is turned on or not. 
    /// </summary> 
    private bool isSuspended = false; 


    // New overridden method 
    /// <summary> 
    /// Intercepts WndProc messages. We are looking for the screen suspend activity. From it, we will return that we are able to suspend and we ourselves will suspend. 
    /// </summary> 
    /// <param name="m">Message to be checked.</param> 
    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg == WM_SYSCOMMAND) 
     { 
      // The 0x000F bits are used to indicate the specific state and must be ignored to see if this is a monitor power event. 
      if ((m.WParam.ToInt32() & 0xFFF0) == SC_MONITORPOWER) 
      { 
       switch (m.WParam.ToInt32() & 0x000F) 
       { 
        case -1: 
         // Display powering on - resume operation 
#if DEBUG 
         System.Diagnostics.Debug.WriteLine("Display powered on."); 
#endif 
         this.isSuspended = false; 
         break; 
        case 0: 
        case 1: 
        case 2: 
         // Display being powered off - suspend operation 
#if DEBUG 
         System.Diagnostics.Debug.WriteLine("Display suspended"); 
#endif 
         this.isSuspended = true; 
         break; 
        default: 
#if DEBUG 
         System.Diagnostics.Debug.WriteLine(string.Format("Unknown power state: {0}", (m.WParam.ToInt32() & 0x000F).ToString("0"))); 
#endif 
         // Assuming that unknown values mean to power off. This is a WAG. 
         this.isSuspended = true; 
         break; 
       } 
      } 
     } 

     base.WndProc(ref m); 
    } 


    // Change to my refreshing timer. 
    /// <summary> 
    /// Called when the refresh timer ticks. This invalidates the form, forcing it to be redrawn, which creates a framerate for us. 
    /// </summary> 
    /// <param name="sender">Who called this method.</param> 
    /// <param name="e">Event Arguments.</param> 
    private void RefreshTimer_Tick(object sender, EventArgs e) 
    { 
     if (this.isSuspended) 
     { 
      // Program is in suspended mode, so don't do anything this update. 
      return; 
     } 

     // Program is not suspended, so invalidate the client area so it can be painted again. 
     this.Invalidate(); 
    } 

Questa modifica si ferma tutto il ridisegno quando una sospensione si chiama (e si ferma la GDI + calcoli) e dopo che lo rende, il salvaschermo "si comporta" con impostazioni di risparmio energetico.

+3

Molto bello - se non ti dispiace, probabilmente lo userò come modello per cambiare un'app di monitoraggio che abbiamo, che colpisce il database piuttosto duramente quando viene eseguito, e inutilmente così quando lo schermo non viene mostrato comunque. –

+0

Non mi dispiace un po 'ed è già parzialmente il tuo successo! Grazie ancora! – Dracorat

1

Ti capita per caso di intercettare il sottocomando 0xF170 (SC_MONITORPOWER) di WM_SYSCOMMAND?

+1

Per rispondere a questo commento, no non lo ero. Tuttavia, ho considerato di farlo e di sospendere la routine di disegno dopo aver ricevuto il messaggio. Questa considerazione alla fine ha portato alla risoluzione che ora aggiungerò e accetto come risposta. Comunque, tu eri un trampolino di lancio chiave lungo la strada e volevo fartelo sapere quando ti ho votato. – Dracorat

+0

Contento di essere almeno di qualche aiuto;) –

Problemi correlati