File: MS\Internal\Automation\MenuTracker.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\UIAutomation\UIAutomationClient\UIAutomationClient.csproj (UIAutomationClient)
// 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: Class used to track context menus appearing 
 
using System;
using System.Windows.Automation;
using System.Diagnostics;
using MS.Win32;
 
namespace MS.Internal.Automation
{
    internal delegate void MenuHandler( AutomationElement rawEl, bool menuHasOpened );
 
    // MenuOpened - Class used to track context menus appearing
    internal class MenuTracker : WinEventWrap
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
 
        #region Constructors
 
        internal MenuTracker(MenuHandler newHandler)
            : base(new int[] {NativeMethods.EVENT_SYSTEM_MENUPOPUPSTART, NativeMethods.EVENT_SYSTEM_MENUPOPUPEND})
        {
            AddCallback(newHandler);
        }
 
        #endregion Constructors
 
 
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
 
        #region Internal Methods
 
        internal override void WinEventProc(int eventId, IntPtr hwnd, int idObject, int idChild, uint eventTime)
        {
            AutomationElement rawEl = null;
            bool menuHasOpened = eventId == NativeMethods.EVENT_SYSTEM_MENUPOPUPSTART;
 
            // Only create a raw element wrapper if the menu has popped up.  Send a
            // null element for menu closed (the element isn't available anymore).
            // If there is any requirement to provide information on what
            // menu element has closed, client code can track menu opened and rely
            // on the following menu closed event to be that menu element.
            if( menuHasOpened )
            {
                // Ignore if this is a bogus hwnd (shouldn't happen)
                if( hwnd == IntPtr.Zero )
                    return;
 
                NativeMethods.HWND nativeHwnd = NativeMethods.HWND.Cast( hwnd );
                if( !SafeNativeMethods.IsWindow( nativeHwnd ) )
                    return;
 
                // Filter... send events for visible hwnds only
                if( !SafeNativeMethods.IsWindowVisible( nativeHwnd ) )
                    return;
 
                rawEl = AutomationElement.FromHandle( hwnd );
            }
 
            // Do callback.  This handler is called due to a WinEvent on the client.  The handler
            // is going to hand off the work of calling out to the client code to another thread
            // via a queue so it is safe to do this callback w/in the lock.
            object [] handlers = GetHandlers();
            Debug.Assert(handlers.Length <= 1, "handlers.Length");
            if( handlers.Length > 0 )
                ( ( MenuHandler )handlers[0] )( rawEl, menuHasOpened );
        }
 
        #endregion Internal Methods
    }
}