File: System\Windows\Documents\WinEventHandler.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
//
// Description: WinEventHandler implementation.
//
 
using System.Runtime.InteropServices;
using MS.Win32;
 
using MS.Internal;
 
namespace System.Windows.Documents
{
    internal class WinEventHandler : IDisposable
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
 
        #region Constructors
 
        // ctor that takes a range of events
        internal WinEventHandler(int eventMin, int eventMax)
        {
            _eventMin = eventMin;
            _eventMax = eventMax;
 
            _winEventProc = new NativeMethods.WinEventProcDef(WinEventDefaultProc);
            // Keep the garbage collector from moving things around
            _gchThis = GCHandle.Alloc(_winEventProc);
 
            // Workaround for bug 150666.
            _shutdownListener = new WinEventHandlerShutDownListener(this);
        }
 
        ~WinEventHandler()
        {
            Clear();
        }
 
        #endregion Constructors
 
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
 
        #region Internal Methods
 
        public void Dispose()
        {
            // no need to call this finalizer.
 
            GC.SuppressFinalize(this);
            Clear();
        }
 
        // callback for the class inherited from this.
        internal virtual void WinEventProc(int eventId, IntPtr hwnd)
        {
        }
 
        internal void Clear()
        {
            // Make sure that the hooks is uninitialzied.
            Stop();
 
            // free GC handle.
            if (_gchThis.IsAllocated)
            {
                _gchThis.Free();
            }
        }
 
        // install WinEvent hook and start getting the callback.
        internal void Start()
        {
            if (_gchThis.IsAllocated)
            {
                _hHook = UnsafeNativeMethods.SetWinEventHook(_eventMin, _eventMax, IntPtr.Zero, _winEventProc,
                                                             0, 0, NativeMethods.WINEVENT_OUTOFCONTEXT);
                if (_hHook == IntPtr.Zero )
                {
                    Stop();
                }
            }
        }
 
        // uninstall WinEvent hook.
        internal void Stop()
        {
            if (_hHook != IntPtr.Zero )
            {
                UnsafeNativeMethods.UnhookWinEvent(_hHook);
                _hHook = IntPtr.Zero ;
            }
 
            if (_shutdownListener != null)
            {
                _shutdownListener.StopListening();
                _shutdownListener = null;
            }
        }
 
        #endregion Internal Methods
 
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------
 
        #region Private Methods
 
        private void WinEventDefaultProc(int winEventHook, int eventId, IntPtr hwnd, int idObject, int idChild, int eventThread, int eventTime)
        {
            WinEventProc(eventId , hwnd);
        }
 
        #endregion Private Methods
 
        #region Private Types
 
        private sealed class WinEventHandlerShutDownListener : ShutDownListener
        {
            public WinEventHandlerShutDownListener(WinEventHandler target)
                : base(target, ShutDownEvents.DispatcherShutdown)
            {
            }
 
            internal override void OnShutDown(object target, object sender, EventArgs e)
            {
                WinEventHandler winEventHandler = (WinEventHandler)target;
                winEventHandler.Stop();
            }
        }
 
        #endregion Private Types
 
        //------------------------------------------------------
        //
        //  Private Fields
        //
        //------------------------------------------------------
 
        #region Private Fields
 
        // min WinEvent.
        private int _eventMin;
 
        // max WinEvent.
        private int _eventMax;
 
        // hook handle
        private IntPtr _hHook;
 
        // the callback.
        private NativeMethods.WinEventProcDef _winEventProc;
 
        // GCHandle to keep the garbage collector from moving things around
        private GCHandle _gchThis;
 
        // shutdown listener
        private WinEventHandlerShutDownListener _shutdownListener;
 
        #endregion Private Fields
    }
}