2016-04-05 102 views
4

要檢測C#Winforms應用程序是否已在一段時間內空閒,最佳方法是什麼?如何檢測Winforms應用程序已空閒一段時間

如果用戶決定ALT + TAB並使用Microsoft Word或其他任何工具進行一些工作30分鐘,則我們的應用程序未使用,我希望我們的應用程序自行終止。

這是一個類似的問題接受的答案: Check if an application is idle for a time period and lock it

然而,得到的答覆是相關的到Windows閒置一段時間後,特定的應用程序。我希望我們的應用程序終止,如果它沒有被用於說,30分鐘。

我看了看這個:

http://www.codeproject.com/Articles/13756/Detecting-Application-Idleness

但是我在評論閱讀,這並不爲多線程應用程序,其中有我們的應用程序是一個工作。 我們的應用程序有一個主要形式,它派生模式和無模式的形式,它使用異步等待填補電網等

然後我看了一下SetWindowsHookEx函數,不確定是否會工作。

肯定有人有一個解決方案(與.NET 4.5兼容的希望):)

TIA

+1

Winform onfocus lost可以與定時器結合使用。 – schultz

+0

你需要用性能計數器來衡量它,然後根據你認爲你的應用程序已經空閒的數字來決定 – Zinov

+0

如果我看到一個應用程序自我終止,我會認爲它崩潰了,這不會留下積極的印象。你確定那是你想要的行爲嗎? –

回答

3

有很多方法可以做到這一點,答案有點取決於你需要做什麼。您清楚明確地瞭解您需要什麼。以下是我開發的可能符合您要求的內容。它正在做的是使用Application.Idle來確定應用程序何時完成處理消息,然後設置一個計時器併爲應用程序過濾(偵聽)所有消息,並且如果接收到相關消息(例如鼠標或鍵盤),那麼它重置計時器。它會忽略鼠標移動,因爲可以在不使用應用程序的情況下將鼠標移到應用程序上。自從我寫這篇文章以來,我已經有一段時間了,所以我不確定細節,但是如果有必要,我可以弄明白。請注意,這是一個控制檯程序,用於使示例更易於嘗試,但代碼僅適用於表單應用程序。

using System; 
using System.Security.Permissions; 
using System.Windows.Forms; 

namespace _121414 
{ 
    static class Program 
    { 
     public static Timer IdleTimer = new Timer(); 
     const int MinuteMicroseconds = 60000; 
     static Form1 f = null; 

     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      LeaveIdleMessageFilter limf = new LeaveIdleMessageFilter(); 
      Application.AddMessageFilter(limf); 
      Application.Idle += new EventHandler(Application_Idle); 
      IdleTimer.Interval = MinuteMicroseconds; // One minute; change as needed 
      IdleTimer.Tick += TimeDone; 
      IdleTimer.Start(); 
      f = new Form1(); 
      Application.Run(f); 
      Application.Idle -= new EventHandler(Application_Idle); 
     } 

     static private void Application_Idle(Object sender, EventArgs e) 
     { 
      if (!IdleTimer.Enabled)  // not yet idling? 
       IdleTimer.Start(); 
     } 

     static private void TimeDone(object sender, EventArgs e) 
     { 
      IdleTimer.Stop(); // not really necessary 
      MessageBox.Show("Auto logoff"); 
      f.Close(); 
     } 

    } 

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] 
    public class LeaveIdleMessageFilter : IMessageFilter 
    { 
     const int WM_NCLBUTTONDOWN = 0x00A1; 
     const int WM_NCLBUTTONUP = 0x00A2; 
     const int WM_NCRBUTTONDOWN = 0x00A4; 
     const int WM_NCRBUTTONUP = 0x00A5; 
     const int WM_NCMBUTTONDOWN = 0x00A7; 
     const int WM_NCMBUTTONUP = 0x00A8; 
     const int WM_NCXBUTTONDOWN = 0x00AB; 
     const int WM_NCXBUTTONUP = 0x00AC; 
     const int WM_KEYDOWN = 0x0100; 
     const int WM_KEYUP = 0x0101; 
     const int WM_MOUSEMOVE = 0x0200; 
     const int WM_LBUTTONDOWN = 0x0201; 
     const int WM_LBUTTONUP = 0x0202; 
     const int WM_RBUTTONDOWN = 0x0204; 
     const int WM_RBUTTONUP = 0x0205; 
     const int WM_MBUTTONDOWN = 0x0207; 
     const int WM_MBUTTONUP = 0x0208; 
     const int WM_XBUTTONDOWN = 0x020B; 
     const int WM_XBUTTONUP = 0x020C; 

     // The Messages array must be sorted due to use of Array.BinarySearch 
     static int[] Messages = new int[] {WM_NCLBUTTONDOWN, 
      WM_NCLBUTTONUP, WM_NCRBUTTONDOWN, WM_NCRBUTTONUP, WM_NCMBUTTONDOWN, 
      WM_NCMBUTTONUP, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, WM_KEYDOWN, WM_KEYUP, 
      WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDOWN, WM_RBUTTONUP, 
      WM_MBUTTONDOWN, WM_MBUTTONUP, WM_XBUTTONDOWN, WM_XBUTTONUP}; 

     public bool PreFilterMessage(ref Message m) 
     { 
      if (m.Msg == WM_MOUSEMOVE) // mouse move is high volume 
       return false; 
      if (!Program.IdleTimer.Enabled)  // idling? 
       return false;   // No 
      if (Array.BinarySearch(Messages, m.Msg) >= 0) 
       Program.IdleTimer.Stop(); 
      return false; 
     } 
    } 
} 
0

你需要決定什麼是 「空閒」 的手段。我假設在所需的時間內沒有收到應用程序的鼠標或鍵盤輸入。

您可以添加一個消息過濾器,以查看所有應用程序範圍的Windows消息。見Application.AddMessageFilter。檢查按鍵和鼠標向下的消息代碼,並記錄它們上次發生的時間,但返回false以便運行時正常處理所有消息。可能的代碼是:

WM_LBUTTONDOWN = 513 
RBUTTONDOWN = 516 
WM_KEYDOWN = 256 

然後在其他地方的一個單獨的計時器中檢查最後一個事件超過30分鐘前的時間。

「終止」應用程序也存在潛在的問題。如果應用程序打開了模態窗體,聽起來好像它可能沒有處於特別安全的狀態來突然中斷。

+0

IIRC - 您可能會遇到問題,因爲過濾器是線程特定的。不確定這是否適用於OP,因爲他特別聲明他需要能夠跨多線程應用程序工作的東西。 – AgapwIesu

+0

儘管OP在其他線程上運行後臺任務,但我的理解是Windows消息仍會到達原始線程 –

+0

那麼我提供了一個示例。嘗試它會很容易。大多數線程不會有UI(消息循環)。消息過濾器可能需要用於每個擁有自己UI(消息循環)的其他線程。如果在不是UI活動的線程中可能有**相關的**活動,則需要單獨檢測。 – user34660