4

I am trying to capture Window's active window changed event. Let's say if user is working on VS and he switches to IE, I want to capture this Active Window Changed Event. I searched on the internet and found many example but nothing seems to work for me.

This is code I have written so far, I am not sure what is wrong in this. I am unable to capture required event through this

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 never gets called, can anybody identify what I am doing wrong programatically or conceptually? I am using Windows 7

Haris Hasan
  • 29,856
  • 10
  • 92
  • 122

2 Answers2

5

You need to be pumping messages to receive WinEvents - and Console.ReadKey() likely doesn't do this. Try using a MessageBox instead for now to test - and replace with a proper message loop later.

From MSDN:

Remarks:
...
The client thread that calls SetWinEventHook must have a message loop in order to receive events
BrendanMcK
  • 14,252
  • 45
  • 54
  • +1 you are right, I am getting event when I use this code in Win Forms App. Any ideas how can I achieve this in a console App? – Haris Hasan Jul 28 '11 at 09:17
  • Another issue is that I am continuously getting the events instead of event on active window change. Any ideas? – Haris Hasan Jul 28 '11 at 09:21
  • There's really little different between a windows app vs console app; you can create windows and pump messages in a console app no problem. However, simplest thing to do is perhaps to P/Invoke to GetMessage/DispatchMessage, and use them just as you would in a plain Win32 app. Are you using any breakpoints in VS here? Be careful when debugging this with VS; since any time a breakpoint is hit, VS will come to the foreground, causing more messages. Also, you might want to use WINEVENT_SKIPOWNTHREAD to ensure that your own messagebox isn't causing you to receive events. – BrendanMcK Jul 28 '11 at 09:43
0

add event loop ans call it in void man i changed your code little and its now working fine.

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
Noaman Akram
  • 3,680
  • 4
  • 20
  • 37