Is there a way to be notified of when focus changes from any window to another window(even between windows applications) such that I can just have my delegate called immedia
You could install a Windows hook (requires some P/Invoke) and watch for messages sent to the windows. This question lists the messages involved in bringing a window to the foreground. Here is the MSDN documentation for installing a hook
SetWinEventHook() is probably your best bet; you can listen to either the EVENT_SYSTEM_FOREGROUND to listen for foreground window changes - or even EVENT_OBJECT_FOCUS to listen for more fine-grain focus changes within apps and within controls.
You'll need to use this with the WINEVENT_OUTOFCONTEXT flag; this means that the change notification will be delivered asynchronously to your own app, so you won't need a separate DLL - you'll still need to P/Invoke though. But the notification won't be instant - there may be a small delay - but that's implied with asynchronous. If you want to do something absolutely immediately with no delay whatsoever, you're going to need to use C++ and an in-process hook (either SetWinEventHook with WINEVENT_INCONTEXT or the SetSetWindowsHookEx-style hook.)
Here's a sample that seems to do what you're looking for:
using System;
using System.Windows;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class ForegroundTracker
{
// Delegate and imports from pinvoke.net:
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);
[DllImport("user32.dll")]
static extern bool UnhookWinEvent(IntPtr hWinEventHook);
// Constants from winuser.h
const uint EVENT_SYSTEM_FOREGROUND = 3;
const uint WINEVENT_OUTOFCONTEXT = 0;
// Need to ensure delegate is not collected while we're using it,
// storing it in a class field is simplest way to do this.
static WinEventDelegate procDelegate = new WinEventDelegate(WinEventProc);
public static void Main()
{
// Listen for foreground changes across all processes/threads on current desktop...
IntPtr hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero,
procDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
// MessageBox provides the necessary mesage loop that SetWinEventHook requires.
MessageBox.Show("Tracking focus, close message box to exit.");
UnhookWinEvent(hhook);
}
static void WinEventProc(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
Console.WriteLine("Foreground changed to {0:x8}", hwnd.ToInt32());
}
}
The example above works like a champ. I refactored it a little to make a class that might be useful. I didn't define all the constants, so you'd need to add a few if you want to trap other events.
using System;
using System.Runtime.InteropServices;
#pragma warning disable 1591
// ReSharper disable InconsistentNaming
namespace MosaiqPerformanceMonitor {
public class EventHook {
public delegate void WinEventDelegate(
IntPtr hWinEventHook, uint eventType,
IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll")]
public static extern IntPtr SetWinEventHook(
uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc,
uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
public const uint EVENT_SYSTEM_FOREGROUND = 3;
public const uint WINEVENT_OUTOFCONTEXT = 0;
public const uint EVENT_OBJECT_CREATE = 0x8000;
readonly WinEventDelegate _procDelegate;
readonly IntPtr _hWinEventHook;
public EventHook(WinEventDelegate handler, uint eventMin, uint eventMax) {
_procDelegate = handler;
_hWinEventHook = SetWinEventHook(eventMin, eventMax, IntPtr.Zero, handler, 0, 0, WINEVENT_OUTOFCONTEXT);
}
public EventHook(WinEventDelegate handler, uint eventMin)
: this(handler, eventMin, eventMin) {
}
public void Stop() {
UnhookWinEvent(_hWinEventHook);
}
// Usage Example for EVENT_OBJECT_CREATE (http://msdn.microsoft.com/en-us/library/windows/desktop/dd318066%28v=vs.85%29.aspx)
// var _objectCreateHook = new EventHook(OnObjectCreate, EventHook.EVENT_OBJECT_CREATE);
// ...
// static void OnObjectCreate(IntPtr hWinEventHook, uint eventType, IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) {
// if (!Win32.GetClassName(hWnd).StartsWith("ClassICareAbout"))
// return;
// Note - in Console program, doesn't fire if you have a Console.ReadLine active, so use a Form
}
}