MSAAWinEventWrap.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / UIAutomation / Win32Providers / MS / Internal / AutomationProxies / MSAAWinEventWrap.cs / 1 / MSAAWinEventWrap.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: Lightweight class to wrap Win32 WinEvents. 
//
// THIS IS VIRTUALLY AN IDENTICAL COPY TO A FILE OF THE SAME NAME IN UIAUTOMATION! 
// IF YOU FIX A


 

 
 
using System;
using System.Collections; 
using System.Runtime.InteropServices;
using MS.Win32;

namespace MS.Internal.AutomationProxies 
{
    // Lightweight class to wrap Win32 WinEvents.  Users of this class would 
    // inherit from MSAAWinEventWrap do the following: 
    //   1. Call the base constructor with a params array of event identifiers
    //   2. Override WinEventProc to provide an implementation. 
    internal class MSAAWinEventWrap
    {
        //-----------------------------------------------------
        // 
        //  Constructors
        // 
        //----------------------------------------------------- 

        #region Constructors 

        // ctor that takes a range of events
        internal MSAAWinEventWrap(int eventMin, int eventMax)
        { 
            _eventMin = eventMin;
            _eventMax = eventMax; 
            _hHooks = new IntPtr[1]; 
            Init();
        } 

        ~MSAAWinEventWrap()
        {
            Clear(); 
        }
 
        #endregion Constructors 

 
        //------------------------------------------------------
        //
        //  Internal Methods
        // 
        //-----------------------------------------------------
 
        #region Internal Methods 

        internal virtual void WinEventProc(int eventId, IntPtr hwnd, int idObject, int idChild) 
        {
            // override this to provide an implementation
        }
 
        internal void Clear()
        { 
            StopListening(); 
            lock(this)
            { 
                _clientCallbacks.Clear ();
            }
            if (_gchThis.IsAllocated)
            { 
                _gchThis.Free();
            } 
        } 

        internal void StartListening() 
        {
            _fBusy = true;

            { 
                // in a single hook, listen for a range of WinEvent types
                _hHooks[0] = Misc.SetWinEventHook(_eventMin, _eventMax, IntPtr.Zero, _winEventProc, 0, 0, _fFlags); 
                if (_hHooks[0] == IntPtr.Zero) 
                {
                    StopListening(); 
                }
            }
            _fBusy = false;
        } 

        internal void StopListening() 
        { 
            // ASSUMPTION: Before StopListening is called, all callback delegates have been removed
            // so that any events received while hooks are being removed become noops (since there's 
            // no handlers for them to call).
            _fBusy = true;

            for (int i=0;i<_hHooks.Length;i++) 
            {
                if (_hHooks[i] != IntPtr.Zero) 
                { 
                    Misc.UnhookWinEvent(_hHooks[i]);
                    _hHooks[i] = IntPtr.Zero; 
                }
            }
            if (_qEvents != null)
            { 
                _qEvents.Clear();
            } 
            _fBusy = false; 
        }
 
        #endregion Internal Methods


        //------------------------------------------------------ 
        //
        //  Private Methods 
        // 
        //------------------------------------------------------
 
        #region Private Methods

        // queue winevents so that the get processed in the order we receive them. If we just
        // dispatch them as we get them, we'll end up getting some _while_ we are processing others, 
        // and end up completing those events out of order, making the event order appear backwards.
        // This code checks whether we are currently processing an event, and if so, queues it so that 
        // we process it when we're done with the current event. 
        private void WinEventReentrancyFilter(int winEventHook, int eventId, IntPtr hwnd, int idObject, int idChild, int eventThread, uint eventTime)
        { 
            if (_fBusy)
            {
                _qEvents.Enqueue(new WinEvent(eventId, hwnd, idObject, idChild));
            } 
            else
            { 
                _fBusy = true; 
                try
                { 
                    WinEventProc( eventId, hwnd, idObject, idChild ); // deliver this event
                }
                catch (Exception e)
                { 
                    if (Misc.IsCriticalException(e))
                    { 
                        throw; 
                    }
 
                    // ignore exceptions for now since we've no way to let clients add exception handlers
                }

                while (_qEvents.Count > 0) 
                {
                    WinEvent winEvent = (WinEvent)_qEvents.Dequeue(); // process queued events 
                    try 
                    {
                        WinEventProc(winEvent._eventId, winEvent._hwnd, winEvent._idObject, winEvent._idChild); 
                    }
                    catch (Exception e)
                    {
                        if (Misc.IsCriticalException(e)) 
                        {
                            throw; 
                        } 

                        // ignore exceptions for now since we've no way to let clients add exception handlers 
                    }
                }
                _fBusy = false;
            } 
        }
 
        private void Init() 
        {
            // Keep the garbage collector from moving things around 
            _winEventProc = new NativeMethods.WinEventProcDef(WinEventReentrancyFilter);
            _gchThis = GCHandle.Alloc(_winEventProc);

            _clientCallbacks = new ArrayList(2); 
            _qEvents = new Queue(16, (float)2.0); // (initial cap, growth factor)
            _fFlags = NativeMethods.WINEVENT_OUTOFCONTEXT; 
        } 

        #endregion Private Methods 

        #region Internal Types

        // ----------------------------------------------------- 
        //
        // Internal Types Declaration 
        // 
        // ------------------------------------------------------
        // Function call to either the Start or Stop Listener 
        internal delegate void StartStopDelegate();

        #endregion Internal Types
 
        //-----------------------------------------------------
        // 
        //  Private Fields 
        //
        //----------------------------------------------------- 

        #region Private Fields

        private class WinEvent 
        {
            internal WinEvent(int eventId, IntPtr hwnd, int idObject, int idChild) 
            { 
                _eventId = eventId;
                _hwnd = hwnd; 
                _idObject = idObject;
                _idChild = idChild;
            }
            public int _eventId; 
            public IntPtr _hwnd;
            public int _idObject; 
            public int _idChild; 
        }
 
        private Queue _qEvents;                // Queue of events waiting to be processed
        private int _eventMin;                 // minimum WinEvent type in range
        private int _eventMax;                 // maximium WinEventType in range
        private IntPtr [] _hHooks;             // the returned handles(s) from SetWinEventHook 
        private bool _fBusy;                   // Flag indicating if we're busy processing
        private int _fFlags;                   // SetWinEventHook flags 
        private GCHandle _gchThis;             // GCHandle to keep GCs from moving this callback 
        private NativeMethods.WinEventProcDef _winEventProc; // the callback handed to USER for WinEvents
        protected ArrayList _clientCallbacks;  // the client callback interface objects 

        #endregion Private Fields
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: Lightweight class to wrap Win32 WinEvents. 
//
// THIS IS VIRTUALLY AN IDENTICAL COPY TO A FILE OF THE SAME NAME IN UIAUTOMATION! 
// IF YOU FIX A


 

 
 
using System;
using System.Collections; 
using System.Runtime.InteropServices;
using MS.Win32;

namespace MS.Internal.AutomationProxies 
{
    // Lightweight class to wrap Win32 WinEvents.  Users of this class would 
    // inherit from MSAAWinEventWrap do the following: 
    //   1. Call the base constructor with a params array of event identifiers
    //   2. Override WinEventProc to provide an implementation. 
    internal class MSAAWinEventWrap
    {
        //-----------------------------------------------------
        // 
        //  Constructors
        // 
        //----------------------------------------------------- 

        #region Constructors 

        // ctor that takes a range of events
        internal MSAAWinEventWrap(int eventMin, int eventMax)
        { 
            _eventMin = eventMin;
            _eventMax = eventMax; 
            _hHooks = new IntPtr[1]; 
            Init();
        } 

        ~MSAAWinEventWrap()
        {
            Clear(); 
        }
 
        #endregion Constructors 

 
        //------------------------------------------------------
        //
        //  Internal Methods
        // 
        //-----------------------------------------------------
 
        #region Internal Methods 

        internal virtual void WinEventProc(int eventId, IntPtr hwnd, int idObject, int idChild) 
        {
            // override this to provide an implementation
        }
 
        internal void Clear()
        { 
            StopListening(); 
            lock(this)
            { 
                _clientCallbacks.Clear ();
            }
            if (_gchThis.IsAllocated)
            { 
                _gchThis.Free();
            } 
        } 

        internal void StartListening() 
        {
            _fBusy = true;

            { 
                // in a single hook, listen for a range of WinEvent types
                _hHooks[0] = Misc.SetWinEventHook(_eventMin, _eventMax, IntPtr.Zero, _winEventProc, 0, 0, _fFlags); 
                if (_hHooks[0] == IntPtr.Zero) 
                {
                    StopListening(); 
                }
            }
            _fBusy = false;
        } 

        internal void StopListening() 
        { 
            // ASSUMPTION: Before StopListening is called, all callback delegates have been removed
            // so that any events received while hooks are being removed become noops (since there's 
            // no handlers for them to call).
            _fBusy = true;

            for (int i=0;i<_hHooks.Length;i++) 
            {
                if (_hHooks[i] != IntPtr.Zero) 
                { 
                    Misc.UnhookWinEvent(_hHooks[i]);
                    _hHooks[i] = IntPtr.Zero; 
                }
            }
            if (_qEvents != null)
            { 
                _qEvents.Clear();
            } 
            _fBusy = false; 
        }
 
        #endregion Internal Methods


        //------------------------------------------------------ 
        //
        //  Private Methods 
        // 
        //------------------------------------------------------
 
        #region Private Methods

        // queue winevents so that the get processed in the order we receive them. If we just
        // dispatch them as we get them, we'll end up getting some _while_ we are processing others, 
        // and end up completing those events out of order, making the event order appear backwards.
        // This code checks whether we are currently processing an event, and if so, queues it so that 
        // we process it when we're done with the current event. 
        private void WinEventReentrancyFilter(int winEventHook, int eventId, IntPtr hwnd, int idObject, int idChild, int eventThread, uint eventTime)
        { 
            if (_fBusy)
            {
                _qEvents.Enqueue(new WinEvent(eventId, hwnd, idObject, idChild));
            } 
            else
            { 
                _fBusy = true; 
                try
                { 
                    WinEventProc( eventId, hwnd, idObject, idChild ); // deliver this event
                }
                catch (Exception e)
                { 
                    if (Misc.IsCriticalException(e))
                    { 
                        throw; 
                    }
 
                    // ignore exceptions for now since we've no way to let clients add exception handlers
                }

                while (_qEvents.Count > 0) 
                {
                    WinEvent winEvent = (WinEvent)_qEvents.Dequeue(); // process queued events 
                    try 
                    {
                        WinEventProc(winEvent._eventId, winEvent._hwnd, winEvent._idObject, winEvent._idChild); 
                    }
                    catch (Exception e)
                    {
                        if (Misc.IsCriticalException(e)) 
                        {
                            throw; 
                        } 

                        // ignore exceptions for now since we've no way to let clients add exception handlers 
                    }
                }
                _fBusy = false;
            } 
        }
 
        private void Init() 
        {
            // Keep the garbage collector from moving things around 
            _winEventProc = new NativeMethods.WinEventProcDef(WinEventReentrancyFilter);
            _gchThis = GCHandle.Alloc(_winEventProc);

            _clientCallbacks = new ArrayList(2); 
            _qEvents = new Queue(16, (float)2.0); // (initial cap, growth factor)
            _fFlags = NativeMethods.WINEVENT_OUTOFCONTEXT; 
        } 

        #endregion Private Methods 

        #region Internal Types

        // ----------------------------------------------------- 
        //
        // Internal Types Declaration 
        // 
        // ------------------------------------------------------
        // Function call to either the Start or Stop Listener 
        internal delegate void StartStopDelegate();

        #endregion Internal Types
 
        //-----------------------------------------------------
        // 
        //  Private Fields 
        //
        //----------------------------------------------------- 

        #region Private Fields

        private class WinEvent 
        {
            internal WinEvent(int eventId, IntPtr hwnd, int idObject, int idChild) 
            { 
                _eventId = eventId;
                _hwnd = hwnd; 
                _idObject = idObject;
                _idChild = idChild;
            }
            public int _eventId; 
            public IntPtr _hwnd;
            public int _idObject; 
            public int _idChild; 
        }
 
        private Queue _qEvents;                // Queue of events waiting to be processed
        private int _eventMin;                 // minimum WinEvent type in range
        private int _eventMax;                 // maximium WinEventType in range
        private IntPtr [] _hHooks;             // the returned handles(s) from SetWinEventHook 
        private bool _fBusy;                   // Flag indicating if we're busy processing
        private int _fFlags;                   // SetWinEventHook flags 
        private GCHandle _gchThis;             // GCHandle to keep GCs from moving this callback 
        private NativeMethods.WinEventProcDef _winEventProc; // the callback handed to USER for WinEvents
        protected ArrayList _clientCallbacks;  // the client callback interface objects 

        #endregion Private Fields
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK