2011-07-28 56 views
4

我想捕獲窗口活動窗口更改事件。假設用戶正在使用VS並切換到IE,我想要捕獲此活動窗口更改事件。我在互聯網上搜索,發現很多例子,但似乎沒有任何工作對我來說。捕獲活動窗口更改事件中的問題

這是我寫到目前爲止的代碼,我不確定這是什麼問題。我無法通過此

class Program 
{ 
    delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime); 

    [DllImport("user32.dll")] 
    static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags); 

    private const uint WINEVENT_OUTOFCONTEXT = 0; 
    private const uint EVENT_SYSTEM_FOREGROUND = 3; 

    static void Main(string[] args) 
    { 
     WinEventDelegate dele = new WinEventDelegate(WinEventProc); 
     IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT); 
     Console.ReadKey(); 
    } 

    static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) 
    { 
     Console.WriteLine("Something"); 
    } 
} 

WinEventProc不會被調用來捕獲所需的事件,有誰能夠確定什麼,我編程或概念做錯了什麼?我正在使用Windows 7

+0

一個很不錯的,工作的解決方案是在這裏:http://stackoverflow.com/a/11943387/134761 – angularsen

回答

5

您需要抽取消息以接收WinEvents - 而Console.ReadKey()可能不會這樣做。現在嘗試使用MessageBox來測試 - 稍後用適當的消息循環進行替換。

MSDN

備註:
...
調用SetWinEventHook客戶端線程必須有消息循環,以接收事件
+0

+1你是對的,我得到的事件,當我使用此代碼在Win窗體應用程序。任何想法如何在控制檯應用程序中實現這一點? –

+0

另一個問題是我在活動窗口更改中不斷獲取事件而不是事件。有任何想法嗎? –

+0

Windows應用程序與控制檯應用程序之間確實有點不同;您可以在控制檯應用程序中創建窗口和泵消息,沒有任何問題。然而,最簡單的做法可能是P /調用GetMessage/DispatchMessage,並像使用普通的Win32應用程序一樣使用它們。 你在VS中使用任何斷點嗎?用VS調試時要小心;因爲任何時候遇到斷點,VS都會到達前臺,導致更多的消息。 此外,您可能希望使用WINEVENT_SKIPOWNTHREAD來確保您自己的消息框不會導致您接收事件。 – BrendanMcK

0

添加事件循環ANS通話它在無效的人我改變你的代碼小 和它現在工作正常

public class Program 
{ 
    delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime); 

    [DllImport("user32.dll")] 
    static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags); 

    private const uint WINEVENT_OUTOFCONTEXT = 0; 
    private const uint EVENT_SYSTEM_FOREGROUND = 3; 

    static void Main(string[] args) 
    { 
     WinEventDelegate dele = new WinEventDelegate(WinEventProc); 
     IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT); 
     EventLoop.Run(); 
     // Console.ReadKey(); 
    } 

    static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) 
    { 
     Console.WriteLine(hwnd.ToString()); 
    } 
} 
    public static class EventLoop 
    { 
     public static void Run() 
     { 
      MSG msg; 

      while (true) 
      { 

       if (PeekMessage(out msg, IntPtr.Zero, 0, 0, PM_REMOVE)) 
       { 
        if (msg.Message == WM_QUIT) 
         break; 

        TranslateMessage(ref msg); 
        DispatchMessage(ref msg); 
       } 
      } 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct MSG 
     { 
      public IntPtr Hwnd; 
      public uint Message; 
      public IntPtr WParam; 
      public IntPtr LParam; 
      public uint Time; 
     } 

     const uint PM_NOREMOVE = 0; 
     const uint PM_REMOVE = 1; 

     const uint WM_QUIT = 0x0012; 

     [DllImport("user32.dll")] 
     private static extern bool PeekMessage(out MSG lpMsg, IntPtr hwnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg); 
     [DllImport("user32.dll")] 
     private static extern bool TranslateMessage(ref MSG lpMsg); 
     [DllImport("user32.dll")] 
     private static extern IntPtr DispatchMessage(ref MSG lpMsg); 
    } 
}e