2012-06-05 55 views
6

我在.Net 4.0中做了一個屏幕保護程序。它基本上只是移動圖像中的位並使用它來顯示它。在計時器上失效並覆蓋onPaint事件。我的屏幕保護程序正在停止屏幕暫停,但我不想它

到目前爲止,它工作得很好 - 但是 - 我注意到它有一個問題。

它正在停止監視器在暫停超時後掛起。由於我安裝了它,我的顯示器現在保持24/7。

事情是,我沒有做任何事情來明確停止省電功能 - 而且我確定我的電腦的省電設置已設置(它們是)。所以我選擇了另一個屏幕保護程序,以確保設置仍然有效。監視器在超時後暫停。

那麼我需要做些什麼才能與電源管理打好關係?我在谷歌搜索這個答案,我發現的一切是如何阻止電源管理,我沒有明確阻止它!我只是想在暫停時間允許暫停。

回答

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

很高興我可以至少有一些幫助;) –