PopupControlService.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Controls / PopupControlService.cs / 2 / PopupControlService.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using MS.Internal; 
using MS.Internal.KnownBoxes; 
using MS.Internal.Media;
using System; 
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using System.Windows; 
using System.Windows.Controls;
using System.Windows.Controls.Primitives; 
using System.Windows.Data; 
using System.Windows.Input;
using System.Windows.Media; 
using System.Windows.Media.Media3D;
using System.Windows.Markup;
using System.Windows.Threading;
using System.Security; 
using System.Security.Permissions;
 
namespace System.Windows.Controls 
{
    ///  
    ///     Service class that provides the input for the ContextMenu and ToolTip services.
    /// 
    internal sealed class PopupControlService
    { 
        #region Creation
 
        /// 
        ///     Critical - this function elevates by accessing InputManger.Current.
        ///     TreatAsSafe: This code simply attaches a call back which is private 
        ///
        [SecurityCritical,SecurityTreatAsSafe]
        internal PopupControlService()
        { 
            InputManager.Current.PostProcessInput += new ProcessInputEventHandler(OnPostProcessInput);
        } 
 
        #endregion
 
        #region Input Handling

        /////////////////////////////////////////////////////////////////////
        /// 
        /// Critical: accesses e.StagingItem.Input. Also this code revieves an event that has
        ///           user initiated set. 
        /// 
        [SecurityCritical]
        private void OnPostProcessInput(object sender, ProcessInputEventArgs e) 
        {
            if (e.StagingItem.Input.RoutedEvent == InputManager.InputReportEvent)
            {
                InputReportEventArgs report = (InputReportEventArgs)e.StagingItem.Input; 
                if (!report.Handled)
                { 
                    if (report.Report.Type == InputType.Mouse) 
                    {
                        RawMouseInputReport mouseReport = (RawMouseInputReport)report.Report; 
                        if ((mouseReport.Actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove)
                        {
                            if ((Mouse.LeftButton == MouseButtonState.Pressed) ||
                                (Mouse.RightButton == MouseButtonState.Pressed)) 
                            {
                                RaiseToolTipClosingEvent(true /* reset */); 
                            } 
                            else
                            { 
                                IInputElement directlyOver = Mouse.PrimaryDevice.RawDirectlyOver;
                                Point pt = Mouse.PrimaryDevice.GetPosition(directlyOver);

                                // If possible, check that the mouse position is within the render bounds 
                                // (avoids mouse capture confusion).
                                if (WithinRenderBounds(directlyOver, pt)) 
                                { 
                                    OnMouseMove(directlyOver, pt);
                                } 
                            }
                        }
                        else if ((mouseReport.Actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate)
                        { 
                            if (LastMouseDirectlyOver != null)
                            { 
                                LastMouseDirectlyOver = null; 
                                if (LastMouseOverWithToolTip != null)
                                { 
                                    RaiseToolTipClosingEvent(true /* reset */);

                                    // When the user moves the cursor outside of the window,
                                    // clear the LastMouseOverWithToolTip property so if the user returns 
                                    // the mouse to the same item, the tooltip will reappear.  If
                                    // the deactivation is coming from a window grabbing capture 
                                    // (such as Drag and Drop) do not clear the property. 
                                    if (MS.Win32.SafeNativeMethods.GetCapture() == IntPtr.Zero)
                                    { 
                                        LastMouseOverWithToolTip = null;
                                    }
                                }
                            } 
                        }
                    } 
                } 
            }
            else if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyDownEvent) 
            {
                ProcessKeyDown(sender, (KeyEventArgs)e.StagingItem.Input);
            }
            else if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyUpEvent) 
            {
                ProcessKeyUp(sender, (KeyEventArgs)e.StagingItem.Input); 
            } 
            else if (e.StagingItem.Input.RoutedEvent == Mouse.MouseUpEvent)
            { 
                ProcessMouseUp(sender, (MouseButtonEventArgs)e.StagingItem.Input);
            }
            else if (e.StagingItem.Input.RoutedEvent == Mouse.MouseDownEvent)
            { 
                RaiseToolTipClosingEvent(true /* reset */);
            } 
        } 

        private bool WithinRenderBounds(IInputElement directlyOver, Point pt) 
        {
            // attempt to cast the DO to a UIElement or UIElement3D
            UIElement directlyOverAsUIElement = directlyOver as UIElement;
            UIElement3D directlyOverAsUIElement3D = (directlyOverAsUIElement == null) ? directlyOver as UIElement3D : null; 

            // in the case we can't tell we will return true 
            bool doesContainPoint = true; 

            if (directlyOverAsUIElement != null || directlyOverAsUIElement3D != null) 
            {

                if (directlyOverAsUIElement != null)
                { 
                    Size comparisonSize = directlyOverAsUIElement.RenderSize;
                    doesContainPoint = ((pt.X >= 0) && (pt.X < comparisonSize.Width) && 
                                        (pt.Y >= 0) && (pt.Y < comparisonSize.Height)); 
                }
                else 
                {
                    Rect comparisonRect = directlyOverAsUIElement3D.Visual2DContentBounds;
                    doesContainPoint = comparisonRect.Contains(pt);
                } 
            }
 
            return doesContainPoint; 
        }
 
        private void OnMouseMove(IInputElement directlyOver, Point pt)
        {
            if (directlyOver != LastMouseDirectlyOver)
            { 
                LastMouseDirectlyOver = directlyOver;
                if (directlyOver != LastMouseOverWithToolTip) 
                { 
                    InspectElementForToolTip(directlyOver as DependencyObject);
                } 
            }
        }
        /////////////////////////////////////////////////////////////////////
        /// 
        /// Critical: This has the ability to spoof input for paste
        /// 
        [SecurityCritical] 
        private void ProcessMouseUp(object sender, MouseButtonEventArgs e)
        { 
            RaiseToolTipClosingEvent(false /* reset */);

            if (!e.Handled)
            { 
                if ((e.ChangedButton == MouseButton.Right) &&
                    (e.RightButton == MouseButtonState.Released)) 
                { 
                    IInputElement directlyOver = Mouse.PrimaryDevice.RawDirectlyOver;
                    if (directlyOver != null) 
                    {
                        Point pt = Mouse.PrimaryDevice.GetPosition(directlyOver);
                        if (RaiseContextMenuOpeningEvent(directlyOver, pt.X, pt.Y,e.UserInitiated))
                        { 
                            e.Handled = true;
                        } 
                    } 
                }
            } 
        }

        /////////////////////////////////////////////////////////////////////
        /// 
        /// Critical: This has the ability to spoof input for paste
        /// 
        [SecurityCritical] 
        private void ProcessKeyDown(object sender, KeyEventArgs e)
        { 
            if (!e.Handled)
            {
                if ((e.SystemKey == Key.F10) && ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift))
                { 
                    RaiseContextMenuOpeningEvent(e);
                } 
            } 
        }
 
        /////////////////////////////////////////////////////////////////////
        ///
        /// Critical: This has the ability to spoof input for paste
        /// 
        [SecurityCritical]
        private void ProcessKeyUp(object sender, KeyEventArgs e) 
        { 
            if (!e.Handled)
            { 
                if (e.Key == Key.Apps)
                {
                    RaiseContextMenuOpeningEvent(e);
                } 
            }
        } 
 
        #endregion
 
        #region ToolTip

        private void InspectElementForToolTip(DependencyObject o)
        { 
            DependencyObject origObj = o;
            if (LocateNearestToolTip(ref o)) 
            { 
                // Show the ToolTip on "o" or keep the current ToolTip active
 
                if (o != null)
                {
                    // A ToolTip value was found and is enabled, proceed to firing the event
 
                    if (LastMouseOverWithToolTip != null)
                    { 
                        // If a ToolTip is active, don't show it anymore 
                        RaiseToolTipClosingEvent(true /* reset */);
                    } 

                    LastChecked = origObj;
                    LastMouseOverWithToolTip = o;
 
                    bool quickShow = _quickShow; // ResetToolTipTimer may reset _quickShow
                    ResetToolTipTimer(); 
 
                    if (quickShow)
                    { 
                        _quickShow = false;
                        RaiseToolTipOpeningEvent();
                    }
                    else 
                    {
                        ToolTipTimer = new DispatcherTimer(DispatcherPriority.Normal); 
                        ToolTipTimer.Interval = TimeSpan.FromMilliseconds(ToolTipService.GetInitialShowDelay(o)); 
                        ToolTipTimer.Tag = BooleanBoxes.TrueBox; // should open
                        ToolTipTimer.Tick += new EventHandler(OnRaiseToolTipOpeningEvent); 
                        ToolTipTimer.Start();
                    }
                }
            } 
            else
            { 
                // If a ToolTip is active, don't show it anymore 
                RaiseToolTipClosingEvent(true /* reset */);
 
                // No longer over an item with a tooltip
                LastMouseOverWithToolTip = null;
            }
        } 

        ///  
        ///     Finds the nearest element with an enabled tooltip. 
        /// 
        ///  
        ///     The most "leaf" element to start looking at.
        ///     This element will be replaced with the element that
        ///     contains an active tooltip OR null if the element
        ///     is already in play. 
        /// 
        /// True if there is an active tooltip in play. 
        private bool LocateNearestToolTip(ref DependencyObject o) 
        {
            IInputElement element = o as IInputElement; 
            if (element != null)
            {
                FindToolTipEventArgs args = new FindToolTipEventArgs();
                element.RaiseEvent(args); 

                if (args.TargetElement != null) 
                { 
                    // Open this element's ToolTip
                    o = args.TargetElement; 
                    return true;
                }
                else if (args.KeepCurrentActive)
                { 
                    // Keep the current ToolTip active
                    o = null; 
                    return true; 
                }
            } 

            // Close any existing ToolTips
            return false;
        } 

        internal bool StopLookingForToolTip(DependencyObject o) 
        { 
            if ((o == LastChecked) || (o == LastMouseOverWithToolTip) || (o == _currentToolTip) || WithinCurrentToolTip(o))
            { 
                // In this case, don't show the ToolTip, but the current ToolTip is still OK to show.
                return true;
            }
 
            return false;
        } 
 
        private bool WithinCurrentToolTip(DependencyObject o)
        { 
            // If no current tooltip, then no need to look
            if (_currentToolTip == null)
            {
                return false; 
            }
 
            DependencyObject v = o as Visual; 
            if (v == null)
            { 
                ContentElement ce = o as ContentElement;
                if (ce != null)
                {
                    v = FindContentElementParent(ce); 
                }
                else 
                { 
                    v = o as Visual3D;
                } 
            }

            return (v != null) &&
                   ((v is Visual && ((Visual)v).IsDescendantOf(_currentToolTip)) || 
                    (v is Visual3D && ((Visual3D)v).IsDescendantOf(_currentToolTip)));
        } 
 
        private void ResetToolTipTimer()
        { 
            if (_toolTipTimer != null)
            {
                _toolTipTimer.Stop();
                _toolTipTimer = null; 
                _quickShow = false;
            } 
        } 

        private void OnRaiseToolTipOpeningEvent(object sender, EventArgs e) 
        {
            RaiseToolTipOpeningEvent();
        }
 
        private void RaiseToolTipOpeningEvent()
        { 
            ResetToolTipTimer(); 

            if (_forceCloseTimer != null) 
            {
                OnForceClose(null, EventArgs.Empty);
            }
 
            DependencyObject o = LastMouseOverWithToolTip;
            if (o != null) 
            { 
                bool show = true;
 
                IInputElement element = o as IInputElement;
                if (element != null)
                {
                    ToolTipEventArgs args = new ToolTipEventArgs(true); 
                    element.RaiseEvent(args);
 
                    show = !args.Handled; 
                }
 
                if (show)
                {
                    object tooltip = ToolTipService.GetToolTip(o);
                    ToolTip tip = tooltip as ToolTip; 
                    if (tip != null)
                    { 
                        _currentToolTip = tip; 
                        _ownToolTip = false;
                    } 
                    else if ((_currentToolTip == null) || !_ownToolTip)
                    {
                        _currentToolTip = new ToolTip();
                        _ownToolTip = true; 
                        _currentToolTip.SetValue(ServiceOwnedProperty, BooleanBoxes.TrueBox);
 
                        // Bind the content of the tooltip to the ToolTip attached property 
                        Binding binding = new Binding();
                        binding.Path = new PropertyPath(ToolTipService.ToolTipProperty); 
                        binding.Mode = BindingMode.OneWay;
                        binding.Source = o;
                        _currentToolTip.SetBinding(ToolTip.ContentProperty, binding);
                    } 

                    if (!_currentToolTip.StaysOpen) 
                    { 
                        // The popup takes capture in this case, which causes us to hit test to the wrong window.
                        // We do not support this scenario. Cleanup and then throw and exception. 
                        throw new NotSupportedException(SR.Get(SRID.ToolTipStaysOpenFalseNotAllowed));
                    }

                    _currentToolTip.SetValue(OwnerProperty, o); 
                    _currentToolTip.Closed += OnToolTipClosed;
                    _currentToolTip.IsOpen = true; 
 
                    ToolTipTimer = new DispatcherTimer(DispatcherPriority.Normal);
                    ToolTipTimer.Interval = TimeSpan.FromMilliseconds(ToolTipService.GetShowDuration(o)); 
                    ToolTipTimer.Tick += new EventHandler(OnRaiseToolTipClosingEvent);
                    ToolTipTimer.Start();
                }
            } 
        }
 
        private void OnRaiseToolTipClosingEvent(object sender, EventArgs e) 
        {
            RaiseToolTipClosingEvent(false /* reset */); 
        }

        /// 
        ///     Closes the current tooltip, firing a Closing event if necessary. 
        /// 
        ///  
        ///     When false, will continue to treat input as if the tooltip were open so that 
        ///     the tooltip of the current element won't re-open. Example: Clicking on a button
        ///     will hide the tooltip, but when the mouse is released, the tooltip should not 
        ///     appear unless the mouse is moved off and then back on the button.
        /// 
        private void RaiseToolTipClosingEvent(bool reset)
        { 
            ResetToolTipTimer();
 
            if (reset) 
            {
                LastChecked = null; 
            }

            DependencyObject o = LastMouseOverWithToolTip;
            if (o != null) 
            {
                if (_currentToolTip != null) 
                { 
                    bool isOpen = _currentToolTip.IsOpen;
 
                    try
                    {
                        if (isOpen)
                        { 
                            IInputElement element = o as IInputElement;
                            if (element != null) 
                            { 
                                element.RaiseEvent(new ToolTipEventArgs(false));
                            } 
                        }
                    }
                    finally
                    { 
                        if (isOpen)
                        { 
                            _currentToolTip.IsOpen = false; 

                            // Keep references and owner set for the fade out or slide animation 
                            // Owner is released when animation completes
                            _forceCloseTimer = new DispatcherTimer(DispatcherPriority.Normal);
                            _forceCloseTimer.Interval = Popup.AnimationDelayTime;
                            _forceCloseTimer.Tick += new EventHandler(OnForceClose); 
                            _forceCloseTimer.Tag = _currentToolTip;
                            _forceCloseTimer.Start(); 
 
                            _quickShow = true;
                            ToolTipTimer = new DispatcherTimer(DispatcherPriority.Normal); 
                            ToolTipTimer.Interval = TimeSpan.FromMilliseconds(ToolTipService.GetBetweenShowDelay(o));
                            ToolTipTimer.Tick += new EventHandler(OnBetweenShowDelay);
                            ToolTipTimer.Start();
                        } 
                        else
                        { 
                            // Release owner now 
                            _currentToolTip.ClearValue(OwnerProperty);
 
                            if (_ownToolTip)
                                BindingOperations.ClearBinding(_currentToolTip, ToolTip.ContentProperty);
                        }
 
                        _currentToolTip = null;
                    } 
                } 
            }
        } 

        // Clear owner when tooltip has closed
        private void OnToolTipClosed(object sender, EventArgs e)
        { 
            ToolTip toolTip = (ToolTip)sender;
            toolTip.Closed -= OnToolTipClosed; 
            toolTip.ClearValue(OwnerProperty); 

            if ((bool)toolTip.GetValue(ServiceOwnedProperty)) 
            {
                BindingOperations.ClearBinding(toolTip, ToolTip.ContentProperty);
            }
        } 

        // The previous tooltip hasn't closed and we are trying to open a new one 
        private void OnForceClose(object sender, EventArgs e) 
        {
            _forceCloseTimer.Stop(); 
            ToolTip toolTip = (ToolTip)_forceCloseTimer.Tag;
            toolTip.ForceClose();
            _forceCloseTimer = null;
        } 

        private void OnBetweenShowDelay(object source, EventArgs e) 
        { 
            ResetToolTipTimer();
        } 

        private IInputElement LastMouseDirectlyOver
        {
            get 
            {
                if (_lastMouseDirectlyOver != null) 
                { 
                    IInputElement e = (IInputElement)_lastMouseDirectlyOver.Target;
                    if (e != null) 
                    {
                        return e;
                    }
                    else 
                    {
                        // Stale reference 
                        _lastMouseDirectlyOver = null; 
                    }
                } 

                return null;
            }
 
            set
            { 
                if (value == null) 
                {
                    _lastMouseDirectlyOver = null; 
                }
                else if (_lastMouseDirectlyOver == null)
                {
                    _lastMouseDirectlyOver = new WeakReference(value); 
                }
                else 
                { 
                    _lastMouseDirectlyOver.Target = value;
                } 
            }
        }

        private DependencyObject LastMouseOverWithToolTip 
        {
            get 
            { 
                if (_lastMouseOverWithToolTip != null)
                { 
                    DependencyObject o = (DependencyObject)_lastMouseOverWithToolTip.Target;
                    if (o != null)
                    {
                        return o; 
                    }
                    else 
                    { 
                        // Stale reference
                        _lastMouseOverWithToolTip = null; 
                    }
                }

                return null; 
            }
 
            set 
            {
                if (value == null) 
                {
                    _lastMouseOverWithToolTip = null;
                }
                else if (_lastMouseOverWithToolTip == null) 
                {
                    _lastMouseOverWithToolTip = new WeakReference(value); 
                } 
                else
                { 
                    _lastMouseOverWithToolTip.Target = value;
                }
            }
        } 

        private DependencyObject LastChecked 
        { 
            get
            { 
                if (_lastChecked != null)
                {
                    DependencyObject o = (DependencyObject)_lastChecked.Target;
                    if (o != null) 
                    {
                        return o; 
                    } 
                    else
                    { 
                        // Stale reference
                        _lastChecked = null;
                    }
                } 

                return null; 
            } 

            set 
            {
                if (value == null)
                {
                    _lastChecked = null; 
                }
                else if (_lastChecked == null) 
                { 
                    _lastChecked = new WeakReference(value);
                } 
                else
                {
                    _lastChecked.Target = value;
                } 
            }
        } 
 
        #endregion
 
        #region ContextMenu

        /// 
        ///     Event that fires on ContextMenu when it opens. 
        ///     Located here to avoid circular dependencies.
        ///  
        internal static readonly RoutedEvent ContextMenuOpenedEvent = 
            EventManager.RegisterRoutedEvent("Opened", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(PopupControlService));
 
        /// 
        ///     Event that fires on ContextMenu when it closes.
        ///     Located here to avoid circular dependencies.
        ///  
        internal static readonly RoutedEvent ContextMenuClosedEvent =
            EventManager.RegisterRoutedEvent("Closed", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(PopupControlService)); 
 
        /////////////////////////////////////////////////////////////////////
        /// 
        /// Critical: This has the ability to spoof input for paste since it passes user initiated bit
        ///
        [SecurityCritical]
        private void RaiseContextMenuOpeningEvent(KeyEventArgs e) 
        {
            IInputElement source = e.OriginalSource as IInputElement; 
            if (source != null) 
            {
                if (RaiseContextMenuOpeningEvent(source, -1.0, -1.0,e.UserInitiated)) 
                {
                    e.Handled = true;
                }
            } 
        }
 
        /// 
        /// Critical: This has the ability to spoof input for paste since it passes user initiated bit
        /// 
        [SecurityCritical]
        private bool RaiseContextMenuOpeningEvent(IInputElement source, double x, double y,bool userInitiated)
        {
            // Fire the event 
            ContextMenuEventArgs args = new ContextMenuEventArgs(source, true /* opening */, x, y);
            DependencyObject sourceDO = source as DependencyObject; 
            if (userInitiated && sourceDO != null) 
            {
                if (InputElement.IsUIElement(sourceDO)) 
                {
                    ((UIElement)sourceDO).RaiseEvent(args, userInitiated);
                }
                else if (InputElement.IsContentElement(sourceDO)) 
                {
                    ((ContentElement)sourceDO).RaiseEvent(args, userInitiated); 
                } 
                else if (InputElement.IsUIElement3D(sourceDO))
                { 
                    ((UIElement3D)sourceDO).RaiseEvent(args, userInitiated);
                }
                else
                { 
                    source.RaiseEvent(args);
                } 
            } 
            else
            { 
                source.RaiseEvent(args);
            }

 
            if (!args.Handled)
            { 
                // No one handled the event, auto show any available ContextMenus 

                // Saved from the bubble up the tree where we looked for a set ContextMenu property 
                DependencyObject o = args.TargetElement;
                if ((o != null) && ContextMenuService.ContextMenuIsEnabled(o))
                {
                    // Retrieve the value 
                    object menu = ContextMenuService.GetContextMenu(o);
                    ContextMenu cm = menu as ContextMenu; 
                    cm.SetValue(OwnerProperty, o); 
                    cm.Closed += new RoutedEventHandler(OnContextMenuClosed);
 
                    if ((x == -1.0) && (y == -1.0))
                    {
                        // We infer this to mean that the ContextMenu was opened with the keyboard
                        cm.Placement = PlacementMode.Center; 
                    }
                    else 
                    { 
                        // If there is a CursorLeft and CursorTop, it was opened with the mouse.
                        cm.Placement = PlacementMode.MousePoint; 
                    }

                    // Clear any open tooltips
                    RaiseToolTipClosingEvent(true /*reset */); 

                    cm.IsOpen = true; 
 
                    return true; // A menu was opened
                } 

                return false; // There was no menu to open
            }
 
            // Clear any open tooltips since someone else opened one
            RaiseToolTipClosingEvent(true /*reset */); 
 
            return true; // The event was handled by someone else
        } 


        private void OnContextMenuClosed(object source, RoutedEventArgs e)
        { 
            ContextMenu cm = source as ContextMenu;
            if (cm != null) 
            { 
                cm.Closed -= OnContextMenuClosed;
 
                DependencyObject o = (DependencyObject)cm.GetValue(OwnerProperty);
                if (o != null)
                {
                    cm.ClearValue(OwnerProperty); 

                    UIElement uie = GetTarget(o); 
                    if (uie != null) 
                    {
                        if (!IsPresentationSourceNull(uie)) 
                        {
                            IInputElement inputElement = (o is ContentElement || o is UIElement3D) ? (IInputElement)o : (IInputElement)uie;
                            ContextMenuEventArgs args = new ContextMenuEventArgs(inputElement, false /*opening */);
                            inputElement.RaiseEvent(args); 
                        }
                    } 
                } 
            }
        } 

        /// 
        /// Critical - as this gets PresentationSource.
        /// Safe - as the value is not returned but is only checked for null. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private static bool IsPresentationSourceNull(DependencyObject uie) 
        {
            return PresentationSource.CriticalFromVisual(uie) == null; 
        }

        #endregion
 
        #region Helpers
 
        internal static DependencyObject FindParent(DependencyObject o) 
        {
            // see if o is a Visual or a Visual3D 
            DependencyObject v = o as Visual;
            if (v == null)
            {
                v = o as Visual3D; 
            }
 
            ContentElement ce = (v == null) ? o as ContentElement : null; 

            if (ce != null) 
            {
                o = ContentOperations.GetParent(ce);
                if (o != null)
                { 
                    return o;
                } 
                else 
                {
                    FrameworkContentElement fce = ce as FrameworkContentElement; 
                    if (fce != null)
                    {
                        return fce.Parent;
                    } 
                }
            } 
            else if (v != null) 
            {
                return VisualTreeHelper.GetParent(v); 
            }

            return null;
        } 

        internal static DependencyObject FindContentElementParent(ContentElement ce) 
        { 
            DependencyObject nearestVisual = null;
            DependencyObject o = ce; 

            while (o != null)
            {
                nearestVisual = o as Visual; 
                if (nearestVisual != null)
                { 
                    break; 
                }
 
                nearestVisual = o as Visual3D;
                if (nearestVisual != null)
                {
                    break; 
                }
 
                ce = o as ContentElement; 
                if (ce != null)
                { 
                    o = ContentOperations.GetParent(ce);
                    if (o == null)
                    {
                        FrameworkContentElement fce = ce as FrameworkContentElement; 
                        if (fce != null)
                        { 
                            o = fce.Parent; 
                        }
                    } 
                }
                else
                {
                    // This could be application. 
                    break;
                } 
            } 

            return nearestVisual; 
        }

        internal static bool IsElementEnabled(DependencyObject o)
        { 
            bool enabled = true;
            UIElement uie = o as UIElement; 
            ContentElement ce = (uie == null) ? o as ContentElement : null; 
            UIElement3D uie3D = (uie == null && ce == null) ? o as UIElement3D : null;
 
            if (uie != null)
            {
                enabled = uie.IsEnabled;
            } 
            else if (ce != null)
            { 
                enabled = ce.IsEnabled; 
            }
            else if (uie3D != null) 
            {
                enabled = uie3D.IsEnabled;
            }
 
            return enabled;
        } 
 
        internal static PopupControlService Current
        { 
            get
            {
                return FrameworkElement.PopupControlService;
            } 
        }
 
        internal ToolTip CurrentToolTip 
        {
            get 
            {
                return _currentToolTip;
            }
        } 

        private DispatcherTimer ToolTipTimer 
        { 
            get
            { 
                return _toolTipTimer;
            }
            set
            { 
                ResetToolTipTimer();
                _toolTipTimer = value; 
            } 
        }
 
        /// 
        ///     Returns the UIElement target
        /// 
        private static UIElement GetTarget(DependencyObject o) 
        {
            UIElement uie = o as UIElement; 
            if (uie == null) 
            {
                ContentElement ce = o as ContentElement; 
                if (ce != null)
                {
                    DependencyObject ceParent = FindContentElementParent(ce);
 
                    // attempt to cast to a UIElement
                    uie = ceParent as UIElement; 
                    if (uie == null) 
                    {
                        // target can't be a UIElement3D - so get the nearest containing UIElement 
                        UIElement3D uie3D = ceParent as UIElement3D;
                        if (uie3D != null)
                        {
                            uie = UIElementHelper.GetContainingUIElement2D(uie3D); 
                        }
                    } 
                } 
                else
                { 
                    // it wasn't a UIElement or ContentElement, try one last cast to UIElement3D
                    // target can't be a UIElement3D - so get the nearest containing UIElement
                    UIElement3D uie3D = o as UIElement3D;
 
                    if (uie3D != null)
                    { 
                        uie = UIElementHelper.GetContainingUIElement2D(uie3D); 
                    }
                } 
            }

            return uie;
        } 

        ///  
        ///     Indicates whether the service owns the tooltip 
        /// 
        private static readonly DependencyProperty ServiceOwnedProperty = 
            DependencyProperty.RegisterAttached("ServiceOwned",                 // Name
                                                typeof(bool),                   // Type
                                                typeof(PopupControlService),    // Owner
                                                new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); 

        ///  
        ///     Stores the original element on which to fire the closed event 
        /// 
        internal static readonly DependencyProperty OwnerProperty = 
            DependencyProperty.RegisterAttached("Owner",                        // Name
                                                typeof(DependencyObject),       // Type
                                                typeof(PopupControlService),    // Owner
                                                new FrameworkPropertyMetadata((DependencyObject)null, // Default Value 
                                                                               new PropertyChangedCallback(OnOwnerChanged)));
 
        // When the owner changes, coerce all attached properties from the service 
        private static void OnOwnerChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        { 
            if (o is ContextMenu)
            {
                o.CoerceValue(ContextMenu.HorizontalOffsetProperty);
                o.CoerceValue(ContextMenu.VerticalOffsetProperty); 
                o.CoerceValue(ContextMenu.PlacementTargetProperty);
                o.CoerceValue(ContextMenu.PlacementRectangleProperty); 
                o.CoerceValue(ContextMenu.PlacementProperty); 
                o.CoerceValue(ContextMenu.HasDropShadowProperty);
            } 
            else if (o is ToolTip)
            {
                o.CoerceValue(ToolTip.HorizontalOffsetProperty);
                o.CoerceValue(ToolTip.VerticalOffsetProperty); 
                o.CoerceValue(ToolTip.PlacementTargetProperty);
                o.CoerceValue(ToolTip.PlacementRectangleProperty); 
                o.CoerceValue(ToolTip.PlacementProperty); 
                o.CoerceValue(ToolTip.HasDropShadowProperty);
            } 
        }

        // Returns the value of dp on the Owner if it is set there,
        // otherwise returns the value set on o (the tooltip or contextmenu) 
        internal static object CoerceProperty(DependencyObject o, object value, DependencyProperty dp)
        { 
            DependencyObject owner = (DependencyObject)o.GetValue(OwnerProperty); 
            if (owner != null)
            { 
                bool hasModifiers;
                if (owner.GetValueSource(dp, null, out hasModifiers) != BaseValueSourceInternal.Default || hasModifiers)
                {
                    // Return a value if it is set on the owner 
                    return owner.GetValue(dp);
                } 
                else if (dp == ToolTip.PlacementTargetProperty || dp == ContextMenu.PlacementTargetProperty) 
                {
                    UIElement uie = GetTarget(owner); 

                    // If it is the PlacementTarget property, return the owner itself
                    if (uie != null)
                        return uie; 
                }
            } 
            return value; 
        }
 
        #endregion

        #region Data
 
        private DispatcherTimer _toolTipTimer;
        private bool _quickShow = false; 
        private WeakReference _lastMouseDirectlyOver; 
        private WeakReference _lastMouseOverWithToolTip;
        private WeakReference _lastChecked; 
        private ToolTip _currentToolTip;
        private DispatcherTimer _forceCloseTimer;
        private bool _ownToolTip;
 
        #endregion
    } 
} 

 

// 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