2011-07-28 58 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