2012-06-05 4 views
6

私は.Net 4.0でスクリーンセーバーを作った。基本的には、イメージ内のビットを移動して、タイマーに.Invalidateを使用して表示し、onPaintイベントをオーバーライドします。私のスクリーンセーバーはスクリーンの中断を止めていますが、私はしたくありません

これまでのところ、それは素晴らしい作品ですが、私はそれに1つの問題があることに気付きました。

サスペンドタイムアウト後にモニタが停止するのを止めています。私はそれをインストールして以来、私のモニターは今24/7にとどまっています。

パワーセービング機能を特に停止するために何もしませんでした。私のコンピュータの省電力設定が設定されていることを確認しました。だから私は設定がまだ動作していることを確認するために別のスクリーンセーバーを選んだ。タイムアウト後にモニタが一時停止しました。

パワーマネージメントでうまくいくためには、何が必要ですか? Googleでこの回答を検索したところ、パワーマネージメントをブロックする方法がわかりました。明示的にブロックしていませんでした。私はちょうどそれが時であることを許可されるサスペンドをほしい。

答えて

1

私のプログラムは「いいです」にすることができました。私はなぜこれが動作し、元のコードはしなかったのかわかりませんが、これだけでは機能しません - 実際には、画面が中断した後に計算を行わないことでCPUサイクルを減らすので、要するに、私はWndProcメッセージをプレビューして、モニターが中断中のメッセージであることを確認し、それが受信されると、再開するまで再描画をやめます(再開してスクリーンセーバーを有効にしておくことができます)。

コードの変更:

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

この変更を行うには、と呼ばれ、サスペンドすべての再描画を停止する(とGDI +の計算を停止)し、それを行った後、スクリーンセーバーが電源管理設定で「振る舞い」。

+3

非常にクール - あなたが気にしない場合は、私たちが持っている監視アプリケーションを変更するためのテンプレートとしておそらくこれを使用します。とにかく画面が表示されていないときは無意味です。 –

+0

私はちょっと気にしないし、すでに部分的に自分の成功です!再度、感謝します! – Dracorat

1

WM_SYSCOMMANDの0xF170(SC_MONITORPOWER)サブコマンドを誤ってトラップしていませんか?

+1

このコメントに答えるには、私はそうではありませんでした。しかし、私はそうし、メッセージを受け取った後で描画ルーチンを中断することを考えました。この考察は最終的に私が今追加し、答えとして受け入れる解決に導いた。それでも、あなたは道に沿って重要な踏み台になっていました。私があなたに投票したときに、そのことをあなたに伝えたいと思いました。 – Dracorat

+0

喜んで私は少なくともいくつかの助けになることができます;) –

関連する問題