windhuan
11/29/2017 - 10:14 AM

AccessibleEventHelper

利用SetWinEventHook 事件钩子避免SetWindowsHookEx权限问题

    internal static class AccessibleEventHelper
    {
        public static event AccessibleEventHandler EventOccurred;

        private static AccessibleEventType min = AccessibleEventType.EVENT_MIN;
        private static AccessibleEventType max = AccessibleEventType.EVENT_MAX;
        private static IntPtr handle = IntPtr.Zero;
        private static WinEventDelegate internalDelegate;
        private static GCHandle gch;

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

        [DllImport("user32.dll")]
        private static extern bool UnhookWinEvent(IntPtr hWinEventHook);

        private delegate void WinEventDelegate(IntPtr hWinEventHook, AccessibleEventType eventType, IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime);

        public static void Init()
        {
            internalDelegate = new WinEventDelegate(InternalCallback);
            gch = GCHandle.Alloc(internalDelegate);
            handle = SetWinEventHook(min, max, IntPtr.Zero, internalDelegate, 0, 0, 0);
        }

        public static void UnInit()
        {
            UnhookWinEvent(handle);
            handle = IntPtr.Zero;
            try
            {
                gch.Free();
            }
            catch { }
        }

        private static void InternalCallback(IntPtr hWinEventHook, AccessibleEventType eventType, IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime)
        {
            if (hWinEventHook != handle) return;
            AccessibleEventArgs aea = new AccessibleEventArgs(eventType, hwnd, idObject, idChild, dwEventThread, dwmsEventTime);
            if (EventOccurred != null)
                EventOccurred(null, aea);
        }
    }

    internal delegate void AccessibleEventHandler(object sender, AccessibleEventArgs e);

    internal class AccessibleEventArgs : EventArgs
    {
        private AccessibleEventType eventType;
        private IntPtr hWnd;
        private uint idObject;
        private uint idChild;
        private uint dwEventThread;
        private uint dwmsEventTime;

        /// <summary>
        /// Initializes a new instance of the AccessibleEventArgs class.
        /// </summary>
        public AccessibleEventArgs(AccessibleEventType eventType,
            IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime)
        {
            this.eventType = eventType;
            this.hWnd = hwnd;
            this.idObject = idObject;
            this.idChild = idChild;
            this.dwEventThread = dwEventThread;
            this.dwmsEventTime = dwmsEventTime;
        }

        /// <summary>
        /// Type of this accessible event
        /// </summary>
        public AccessibleEventType EventType
        {
            get { return eventType; }
        }

        /// <summary>
        /// Handle of the affected window, if any.
        /// </summary>
        public IntPtr HWnd
        {
            get { return hWnd; }
        }

        /// <summary>
        /// Object ID.
        /// </summary>
        public uint ObjectID
        {
            get { return idObject; }
        }

        /// <summary>
        /// Child ID.
        /// </summary>
        public uint ChildID
        {
            get { return idChild; }
        }

        /// <summary>
        /// The thread that generated this event.
        /// </summary>
        public uint Thread
        {
            get { return dwEventThread; }
        }

        /// <summary>
        /// Time in milliseconds when the event was generated.
        /// </summary>
        public uint Time
        {
            get { return dwmsEventTime; }
        }
    }