2012-06-05 19 views
6

Hice un protector de pantalla en .NET 4.0. Básicamente, solo mueve los bits en una imagen y lo muestra con .Invalidate en un temporizador y anulando el evento onPaint.Mi protector de pantalla está suspendiendo la suspensión de la pantalla, pero no lo quiero

Hasta ahora, funciona muy bien, sin embargo, noté un problema.

Está deteniendo la suspensión del monitor después del tiempo de espera de suspensión. Desde que lo instalé, mi monitor permanece 24/7 ahora.

La cuestión es que no hice nada para detener específicamente las funciones de ahorro de energía, y me he asegurado de que las configuraciones de ahorro de energía de mi computadora estén configuradas (lo son). Entonces elegí otro protector de pantalla solo para asegurarme de que la configuración aún funcionara. El monitor se suspendió después del tiempo de espera.

¿Qué debo hacer entonces para jugar bien con la administración de energía? Busqué esta respuesta en Google y todo lo que encontré es cómo bloquear la administración de energía y ¡no lo bloqueé explícitamente! Solo quiero que se permita la suspensión cuando sea el momento.

Respuesta

1

Pude hacer que mi programa "jugara agradable". No sé por qué funciona esto y el código original no, pero esto no solo funciona: en realidad hace que el programa sea más amigable con el "ahorro de energía" porque reduce los ciclos de CPU al no hacer cálculos después de que la pantalla se suspende. En resumen, obtengo una vista previa de los mensajes de WndProc y busco que el mensaje del monitor esté suspendido y, una vez recibido, dejo de redibujar hasta que se reanude (es posible reanudar y tener el protector de pantalla aún activo).

cambios de código:

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

hacer este cambio se detiene todo el nuevo trazado cuando una suspender se llama (y las paradas de los cálculos de GDI +) y después de lo que es, el protector de pantalla "se comporta" con la configuración de administración de energía.

+3

Muy bien - si no te importa probablemente lo use como una plantilla para cambiar una aplicación de monitoreo que tenemos, que golpea la base de datos bastante difícil cuando se ejecuta, y sin sentido así que cuando la pantalla no se muestra de todos modos. –

+0

¡No me importa un poco y ya es parcialmente tu propio éxito! ¡Gracias de nuevo! – Dracorat

1

¿Por casualidad atrapa accidentalmente el subcomando 0xF170 (SC_MONITORPOWER) de WM_SYSCOMMAND?

+1

Para responder a este comentario, no lo era. Sin embargo, consideré hacerlo y suspender la rutina de dibujo después de recibir el mensaje. Esta consideración finalmente condujo a la resolución que ahora voy a agregar y acepto como respuesta. Aún así, usted fue un paso clave en el camino y quería hacerle saber que lo voté. – Dracorat

+0

Me alegro de que podría ser al menos un poco de ayuda;) –

Cuestiones relacionadas