void Hook(IntPtr hookHandle, EnumWindowEvent @event, IntPtr hWnd, int @object, int child, int threadId,
                  int timestampMs)
        {
            EventHandler <WindowEventArgs> handler;

            switch (@event)
            {
            case EnumWindowEvent.FOREGROUND_CHANGED:
                handler = _activated;
                break;

            case EnumWindowEvent.NAME_CHANGED:
                handler = _textChanged;
                break;

            case EnumWindowEvent.MINIMIZED:
                handler = _minimized;
                break;

            case EnumWindowEvent.UNMIMINIZED:
                handler = _unminimized;
                break;

            default:
                Debug.Write($"Unexpected event {@event}");
                return;
            }

            handler?.Invoke(this, new WindowEventArgs(hWnd));
        }
 void EnsureHook(EnumWindowEvent @event)
 {
     if (!_hooksDictionary.TryGetValue(@event, out var hookId))
     {
         hookId = SetHook(@event);
         _hooksDictionary.Add(@event, hookId);
     }
 }
 void EventAdd(ref EventHandler <WindowEventArgs> handler, EventHandler <WindowEventArgs> user,
               EnumWindowEvent @event)
 {
     lock (_hooksDictionary)
     {
         handler += user;
         this.EnsureHook(@event);
     }
 }
        IntPtr SetHook(EnumWindowEvent @event)
        {
            IntPtr hookId = DllUser32.SetWinEventHook(
                hookMin: @event, hookMax: @event,
                moduleHandle: IntPtr.Zero, callback: _eventProc,
                processId: 0, threadId: 0,
                flags: EnumHookFlags.OUT_OF_CONTEXT);

            if (hookId == IntPtr.Zero)
            {
                throw new Win32Exception();
            }
            return(hookId);
        }
        void EventRemove(ref EventHandler <WindowEventArgs> handler, EventHandler <WindowEventArgs> user,
                         EnumWindowEvent @event)
        {
            lock (_hooksDictionary)
            {
                if (handler != null && handler - user == null)
                {
                    if (!DllUser32.UnhookWinEvent(_hooksDictionary[@event]))
                    {
                        throw new Win32Exception();
                    }
                    bool existed = _hooksDictionary.Remove(@event);
                    Debug.Assert(existed);
                }

                handler -= user;
            }
        }
 internal static extern IntPtr SetWinEventHook(EnumWindowEvent hookMin, EnumWindowEvent hookMax, IntPtr moduleHandle, WinEventProc callback, int processId, int threadId, EnumHookFlags flags);