HostVisual.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 / Core / CSharp / System / Windows / Media / HostVisual.cs / 1 / HostVisual.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//     Host visual. 
//
//----------------------------------------------------------------------------- 

namespace System.Windows.Media
{
    using System; 
    using System.Windows.Threading;
    using System.Windows.Media; 
    using System.Windows.Media.Composition; 
    using System.Diagnostics;
    using System.Collections; 
    using System.Collections.Generic;
    using MS.Internal;
    using System.Resources;
    using System.Runtime.InteropServices; 
    using MS.Win32;
    using System.Threading; 
 
    using SR=MS.Internal.PresentationCore.SR;
    using SRID=MS.Internal.PresentationCore.SRID; 

    /// 
    /// Host visual.
    ///  
    public class HostVisual : ContainerVisual
    { 
        //--------------------------------------------------------------------- 
        //
        //  Constructors 
        //
        //---------------------------------------------------------------------

        #region Constructors 

        ///  
        /// 
        /// 
        public HostVisual() 
        {
            //
            // Set NodeUsesRealizationCaches flag, so that UpdateRealizations
            // will be called when change affecting realizations occurred in 
            // the ancestor. UpdateRealizations override will propagate this
            // infromation to the hosted visual tree. 
            // 

            SetFlags(true, VisualFlags.NodeUsesRealizationCaches); 
        }

        #endregion Constructors
 
        //----------------------------------------------------------------------
        // 
        //  Protected Methods 
        //
        //--------------------------------------------------------------------- 

        #region Protected Methods

        ///  
        /// HitTestCore
        ///  
        protected override HitTestResult HitTestCore( 
            PointHitTestParameters hitTestParameters)
        { 
            //
            // HostVisual never reports itself as being hit. To change this
            // behavior clients should derive from HostVisual and override
            // HitTestCore methods. 
            //
            return null; 
        } 

        ///  
        /// HitTestCore
        /// 
        protected override GeometryHitTestResult HitTestCore(
            GeometryHitTestParameters hitTestParameters) 
        {
            // 
            // HostVisual never reports itself as being hit. To change this 
            // behavior clients should derive from HostVisual and override
            // HitTestCore methods. 
            //
            return null;
        }
 
        #endregion Protected Methods
 
        //---------------------------------------------------------------------- 
        //
        //  Internal Methods 
        //
        //----------------------------------------------------------------------

        #region Internal Methods 

        ///  
        /// 
        /// 
        internal override Rect GetContentBounds() 
        {
            return Rect.Empty;
        }
 
        /// 
        /// 
        ///  
        internal override void RenderContent(RenderContext ctx, bool isOnChannel)
        { 
            //
            // Create and register RenderComplete event handler
            // that will be used to propagate state changes to
            // the hosted visual target. 
            //
 
            if (_propagateState == null) 
            {
                _propagateState = new EventHandler(PropagateState); 
                MediaContext.From(Dispatcher).RenderComplete += _propagateState;
            }

 
            //
            // Make sure that the visual target is properly hosted. 
            // 

            EnsureHostedVisualConnected(ctx.Channel); 
        }

        /// 
        /// 
        /// 
        internal override void FreeContent(DUCE.Channel channel) 
        { 
            if (!channel.IsLayeredWindowChannel)
            { 
                //
                // Unregister RenderComplete event handler if one is registered.
                //
 
                if (_propagateState != null)
                { 
                    MediaContext.From(Dispatcher).RenderComplete -= _propagateState; 
                    _propagateState = null;
                } 

                //
                // Disconnect hosted visual from this channel.
                // 

                using (CompositionEngineLock.Acquire()) 
                { 
                    DisconnectHostedVisual(
                        channel, 
                        /* removeChannelFromCollection */ true);
                }

                base.FreeContent(channel); 
            }
        } 
 
        /// 
        /// 
        /// 
        internal override void UpdateRealizations(RealizationContext ctx)
        {
            // 
            // If transform in one of the the ancestors has chnaged,
            // propagate transform information in order to correclty 
            // compute realizations in the hosted visual tree. State 
            // change will be propagated when channel is committed.
            // 
            Matrix transform = ctx.TransformStack.Peek();

            if (_state.worldTransform != transform)
            { 
                _state.flags |= CompositionTarget.HostStateFlags.WorldTransform;
                _state.worldTransform = transform; 
            } 

            // 
            //


 
        }
 
        ///  
        ///
        ///  
        internal void PropagateState(object sender, EventArgs e)
        {
            //
            // If state has changed, propagate the change to the 
            // visual target and reset the state.
            // 
            if (_state.flags != 0) 
            {
                VisualTarget.HostState state = _state; 

                using (CompositionEngineLock.Acquire())
                {
                    if (_target != null) 
                    {
                        _target.PropagateState(ref state); 
                    } 
                }
 
                _state.flags = 0;
            }
        }
 
        /// 
        /// 
        ///  
        internal void BeginHosting(VisualTarget target)
        { 
            //
            // This method is executed on the visual target thread.
            //
 
            Debug.Assert(target != null);
            Debug.Assert(target.Dispatcher.Thread == Thread.CurrentThread); 
 
            using (CompositionEngineLock.Acquire())
            { 
                //
                // Check if another target is already hosted by this
                // visual and throw exception if this is the case.
                // 
                if (_target != null)
                { 
                    throw new InvalidOperationException( 
                        SR.Get(SRID.VisualTarget_AnotherTargetAlreadyConnected)
                        ); 
                }

                _target = target;
 
                //
                // If HostVisual and VisualTarget on same thread, then call Invalidate 
                // directly. Otherwise post invalidate message to the host visual thread 
                // indicating that content update is required.
                // 
                if (this.CheckAccess())
                {
                    Invalidate();
                } 
                else
                { 
                    Dispatcher.BeginInvoke( 
                        DispatcherPriority.Normal,
                        (DispatcherOperationCallback)delegate(object args) 
                        {
                            Invalidate();
                            return null;
                        }, 
                        null
                        ); 
                } 
            }
        } 

        /// 
        ///
        ///  
        internal void EndHosting()
        { 
            // 
            // This method is executed on the visual target thread.
            // 

            using (CompositionEngineLock.Acquire())
            {
                Debug.Assert(_target != null); 
                Debug.Assert(_target.Dispatcher.Thread == Thread.CurrentThread);
 
                DisconnectHostedVisualOnAllChannels(); 

                _target = null; 
            }
        }

        ///  
        /// Should be called from the VisualTarget thread
        /// when it is safe to access the composition node 
        /// and out of band channel from the VisualTarget thread 
        /// to allow for the handle duplication/channel commit
        ///  
        internal object DoHandleDuplication(object parameters)
        {
            ArrayList paramArray = parameters as ArrayList;
            DUCE.ResourceHandle targetsHandle = DUCE.ResourceHandle.Null; 
            DUCE.Channel channel = paramArray[0] as DUCE.Channel;
            long _requestingGenerationId = (long)paramArray[1]; 
 
            using (CompositionEngineLock.Acquire())
            { 
                //
                // We need to ensure that the generation Id is the same now as
                // it was when this Invoke was posted. There are certain situations
                // in which Connect/Disconnect may have occurred on one thread and 
                // not the other, which would mean we'd try to duplicate a handle from
                // or to a stale channel. We use the generation Id to determine if both 
                // threads are using the same transport. If they're not, we can safely 
                // noop, because the last thread to process the Connect/Disconnect message
                // will remarshal itself to the new channel, causing this Invoke to 
                // eventually be called again
                //
                if (_requestingGenerationId == MediaSystem.GenerationId)
                { 
                    targetsHandle = _target._contentRoot.DuplicateHandle(_target.OutOfBandChannel, channel);
 
                    Debug.Assert(!targetsHandle.IsNull); 

                    _target.OutOfBandChannel.Commit(); 
                }
            }
            return targetsHandle;
        } 

        #endregion Internal Methods 
 

        //--------------------------------------------------------------------- 
        //
        //  Private Methods
        //
        //---------------------------------------------------------------------- 

        #region Private Methods 
 
        /// 
        /// Connects the hosted visual on a channel if necessary. 
        /// 
        private void EnsureHostedVisualConnected(DUCE.Channel channel)
        {
            // 
            // Conditions for connecting VisualTarget to Host Visual:-
            // 1. The channel on which we are rendering should not be synchronous. This 
            //    scenario is not supported currently. 
            // 2. VisualTarget should not be null.
            // 3. They should not be already connected. 
            //
            if (!(channel.IsSynchronous)
                && _target != null
                && !_connectedChannels.Contains(channel) 
                && !channel.IsLayeredWindowChannel)
            { 
                Debug.Assert(IsOnChannel(channel)); 

                DUCE.ResourceHandle targetsHandle = DUCE.ResourceHandle.Null; 

                bool doDuplication = true;

                // 
                // If HostVisual and VisualTarget are on same thread, then we just addref
                // VisualTarget. Otherwise, if on different threads, then we duplicate 
                // VisualTarget onto Hostvisual's channel. 
                //
                if (_target.CheckAccess()) 
                {
                    Debug.Assert(_target._contentRoot.IsOnChannel(channel));
                    Debug.Assert(_target.OutOfBandChannel == MediaContext.CurrentMediaContext.OutOfBandChannel);
                    bool created = _target._contentRoot.CreateOrAddRefOnChannel(channel, VisualTarget.s_contentRootType); 
                    Debug.Assert(!created);
                    targetsHandle = _target._contentRoot.GetHandle(channel); 
                } 
                else
                { 
                    //
                    // Duplicate the target's handle onto our channel.
                    //
                    // We must wait synchronously for the _targets Dispatcher to call 
                    // back and do handle duplication. We can't do handle duplication
                    // on this thread because access to the _target CompositionNode 
                    // is not synchronized. If we duplicated here, we could potentially 
                    // corrupt the _target OutOfBandChannel or the CompositionNode
                    // MultiChannelResource. We have to wait synchronously because 
                    // we need the resulting duplicated handle to hook up as a child
                    // to this HostVisual.
                    //
 
                    ArrayList parameters = new ArrayList(2);
                    parameters.Add(channel); 
                    parameters.Add((object)MediaSystem.GenerationId); 

                    object returnValue = _target.Dispatcher.Invoke( 
                        DispatcherPriority.Normal,
                        TimeSpan.FromMilliseconds(1000),
                        new DispatcherOperationCallback(DoHandleDuplication),
                        parameters 
                        );
 
                    // 
                    // Duplication and flush is complete, we can resume processing
                    // Only if the Invoke succeeded will we have a handle returned. 
                    //
                    if (returnValue != null)
                    {
                        targetsHandle = (DUCE.ResourceHandle)returnValue; 
                    }
                    else 
                    { 
                        // The Invoke didn't complete
                        doDuplication = false; 
                    }
                }

                if (doDuplication) 
                {
                    if (!targetsHandle.IsNull) 
                    { 
                        using (CompositionEngineLock.Acquire())
                        { 
                            DUCE.CompositionNode.InsertChildAt(
                                _proxy.GetHandle(channel),
                                targetsHandle,
                                0, 
                                channel);
                        } 
 
                        _connectedChannels.Add(channel);
 
                        //
                        // Indicate that that content composition root has been
                        // connected, this needs to be taken into account to
                        // properly manage children of this visual. 
                        //
 
                        SetFlags(channel, true, VisualProxyFlags.IsContentNodeConnected); 
                    }
                } 
                else
                {
                    //
                    // We didn't get a handle, because _target belongs to a 
                    // different thread, and the Invoke operation failed. We can't do
                    // anything except try again in the next render pass. We can't 
                    // call Invalidate during the render pass because it pushes up 
                    // flags that are being modified within the render pass, so get
                    // the local Dispatcher to do it for us later. 
                    //
                    Dispatcher.BeginInvoke(
                        DispatcherPriority.Normal,
                        (DispatcherOperationCallback)delegate(object args) 
                        {
                            Invalidate(); 
                            return null; 
                        },
                        null 
                        );
                }
            }
        } 

 
        ///  
        /// Disconnects the hosted visual on all channels we have
        /// connected it to. 
        /// 
        private void DisconnectHostedVisualOnAllChannels()
        {
            foreach (DUCE.Channel channel in _connectedChannels) 
            {
                DisconnectHostedVisual( 
                    channel, 
                    /* removeChannelFromCollection */ false);
            } 

            _connectedChannels.Clear();
        }
 

        ///  
        /// Disconnects the hosted visual on a channel. 
        /// 
        private void DisconnectHostedVisual( 
            DUCE.Channel channel,
            bool removeChannelFromCollection)
        {
            if (_target != null && _connectedChannels.Contains(channel)) 
            {
                DUCE.CompositionNode.RemoveChild( 
                    _proxy.GetHandle(channel), 
                    _target._contentRoot.GetHandle(channel),
                    channel 
                    );

                //
                // Release the targets handle. If we had duplicated the handle, 
                // then this removes the duplicated handle, otherwise just decrease
                // the ref count for VisualTarget. 
                // 

                _target._contentRoot.ReleaseOnChannel(channel); 

                SetFlags(channel, false, VisualProxyFlags.IsContentNodeConnected);

                if (removeChannelFromCollection) 
                {
                    _connectedChannels.Remove(channel); 
                } 
            }
        } 


        /// 
        /// Invalidate this visual. 
        /// 
        private void Invalidate() 
        { 
            SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty);
 
            PropagateChangedFlags();
        }

        #endregion Private Methods 

 
        //--------------------------------------------------------------------- 
        //
        //  Private Fields 
        //
        //---------------------------------------------------------------------

        #region Private Fields 

        private EventHandler _propagateState; 
        private VisualTarget.HostState _state; 

        ///  
        /// The hosted visual target.
        /// 
        /// 
        /// This field is free-threaded and should be accessed from under a lock. 
        /// 
        private VisualTarget _target; 
 
        /// 
        /// The channels we have marshalled the visual target composition root. 
        /// 
        /// 
        /// This field is free-threaded and should be accessed from under a lock.
        ///  
        private List _connectedChannels = new List();
 
        #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: 
//     Host visual. 
//
//----------------------------------------------------------------------------- 

namespace System.Windows.Media
{
    using System; 
    using System.Windows.Threading;
    using System.Windows.Media; 
    using System.Windows.Media.Composition; 
    using System.Diagnostics;
    using System.Collections; 
    using System.Collections.Generic;
    using MS.Internal;
    using System.Resources;
    using System.Runtime.InteropServices; 
    using MS.Win32;
    using System.Threading; 
 
    using SR=MS.Internal.PresentationCore.SR;
    using SRID=MS.Internal.PresentationCore.SRID; 

    /// 
    /// Host visual.
    ///  
    public class HostVisual : ContainerVisual
    { 
        //--------------------------------------------------------------------- 
        //
        //  Constructors 
        //
        //---------------------------------------------------------------------

        #region Constructors 

        ///  
        /// 
        /// 
        public HostVisual() 
        {
            //
            // Set NodeUsesRealizationCaches flag, so that UpdateRealizations
            // will be called when change affecting realizations occurred in 
            // the ancestor. UpdateRealizations override will propagate this
            // infromation to the hosted visual tree. 
            // 

            SetFlags(true, VisualFlags.NodeUsesRealizationCaches); 
        }

        #endregion Constructors
 
        //----------------------------------------------------------------------
        // 
        //  Protected Methods 
        //
        //--------------------------------------------------------------------- 

        #region Protected Methods

        ///  
        /// HitTestCore
        ///  
        protected override HitTestResult HitTestCore( 
            PointHitTestParameters hitTestParameters)
        { 
            //
            // HostVisual never reports itself as being hit. To change this
            // behavior clients should derive from HostVisual and override
            // HitTestCore methods. 
            //
            return null; 
        } 

        ///  
        /// HitTestCore
        /// 
        protected override GeometryHitTestResult HitTestCore(
            GeometryHitTestParameters hitTestParameters) 
        {
            // 
            // HostVisual never reports itself as being hit. To change this 
            // behavior clients should derive from HostVisual and override
            // HitTestCore methods. 
            //
            return null;
        }
 
        #endregion Protected Methods
 
        //---------------------------------------------------------------------- 
        //
        //  Internal Methods 
        //
        //----------------------------------------------------------------------

        #region Internal Methods 

        ///  
        /// 
        /// 
        internal override Rect GetContentBounds() 
        {
            return Rect.Empty;
        }
 
        /// 
        /// 
        ///  
        internal override void RenderContent(RenderContext ctx, bool isOnChannel)
        { 
            //
            // Create and register RenderComplete event handler
            // that will be used to propagate state changes to
            // the hosted visual target. 
            //
 
            if (_propagateState == null) 
            {
                _propagateState = new EventHandler(PropagateState); 
                MediaContext.From(Dispatcher).RenderComplete += _propagateState;
            }

 
            //
            // Make sure that the visual target is properly hosted. 
            // 

            EnsureHostedVisualConnected(ctx.Channel); 
        }

        /// 
        /// 
        /// 
        internal override void FreeContent(DUCE.Channel channel) 
        { 
            if (!channel.IsLayeredWindowChannel)
            { 
                //
                // Unregister RenderComplete event handler if one is registered.
                //
 
                if (_propagateState != null)
                { 
                    MediaContext.From(Dispatcher).RenderComplete -= _propagateState; 
                    _propagateState = null;
                } 

                //
                // Disconnect hosted visual from this channel.
                // 

                using (CompositionEngineLock.Acquire()) 
                { 
                    DisconnectHostedVisual(
                        channel, 
                        /* removeChannelFromCollection */ true);
                }

                base.FreeContent(channel); 
            }
        } 
 
        /// 
        /// 
        /// 
        internal override void UpdateRealizations(RealizationContext ctx)
        {
            // 
            // If transform in one of the the ancestors has chnaged,
            // propagate transform information in order to correclty 
            // compute realizations in the hosted visual tree. State 
            // change will be propagated when channel is committed.
            // 
            Matrix transform = ctx.TransformStack.Peek();

            if (_state.worldTransform != transform)
            { 
                _state.flags |= CompositionTarget.HostStateFlags.WorldTransform;
                _state.worldTransform = transform; 
            } 

            // 
            //


 
        }
 
        ///  
        ///
        ///  
        internal void PropagateState(object sender, EventArgs e)
        {
            //
            // If state has changed, propagate the change to the 
            // visual target and reset the state.
            // 
            if (_state.flags != 0) 
            {
                VisualTarget.HostState state = _state; 

                using (CompositionEngineLock.Acquire())
                {
                    if (_target != null) 
                    {
                        _target.PropagateState(ref state); 
                    } 
                }
 
                _state.flags = 0;
            }
        }
 
        /// 
        /// 
        ///  
        internal void BeginHosting(VisualTarget target)
        { 
            //
            // This method is executed on the visual target thread.
            //
 
            Debug.Assert(target != null);
            Debug.Assert(target.Dispatcher.Thread == Thread.CurrentThread); 
 
            using (CompositionEngineLock.Acquire())
            { 
                //
                // Check if another target is already hosted by this
                // visual and throw exception if this is the case.
                // 
                if (_target != null)
                { 
                    throw new InvalidOperationException( 
                        SR.Get(SRID.VisualTarget_AnotherTargetAlreadyConnected)
                        ); 
                }

                _target = target;
 
                //
                // If HostVisual and VisualTarget on same thread, then call Invalidate 
                // directly. Otherwise post invalidate message to the host visual thread 
                // indicating that content update is required.
                // 
                if (this.CheckAccess())
                {
                    Invalidate();
                } 
                else
                { 
                    Dispatcher.BeginInvoke( 
                        DispatcherPriority.Normal,
                        (DispatcherOperationCallback)delegate(object args) 
                        {
                            Invalidate();
                            return null;
                        }, 
                        null
                        ); 
                } 
            }
        } 

        /// 
        ///
        ///  
        internal void EndHosting()
        { 
            // 
            // This method is executed on the visual target thread.
            // 

            using (CompositionEngineLock.Acquire())
            {
                Debug.Assert(_target != null); 
                Debug.Assert(_target.Dispatcher.Thread == Thread.CurrentThread);
 
                DisconnectHostedVisualOnAllChannels(); 

                _target = null; 
            }
        }

        ///  
        /// Should be called from the VisualTarget thread
        /// when it is safe to access the composition node 
        /// and out of band channel from the VisualTarget thread 
        /// to allow for the handle duplication/channel commit
        ///  
        internal object DoHandleDuplication(object parameters)
        {
            ArrayList paramArray = parameters as ArrayList;
            DUCE.ResourceHandle targetsHandle = DUCE.ResourceHandle.Null; 
            DUCE.Channel channel = paramArray[0] as DUCE.Channel;
            long _requestingGenerationId = (long)paramArray[1]; 
 
            using (CompositionEngineLock.Acquire())
            { 
                //
                // We need to ensure that the generation Id is the same now as
                // it was when this Invoke was posted. There are certain situations
                // in which Connect/Disconnect may have occurred on one thread and 
                // not the other, which would mean we'd try to duplicate a handle from
                // or to a stale channel. We use the generation Id to determine if both 
                // threads are using the same transport. If they're not, we can safely 
                // noop, because the last thread to process the Connect/Disconnect message
                // will remarshal itself to the new channel, causing this Invoke to 
                // eventually be called again
                //
                if (_requestingGenerationId == MediaSystem.GenerationId)
                { 
                    targetsHandle = _target._contentRoot.DuplicateHandle(_target.OutOfBandChannel, channel);
 
                    Debug.Assert(!targetsHandle.IsNull); 

                    _target.OutOfBandChannel.Commit(); 
                }
            }
            return targetsHandle;
        } 

        #endregion Internal Methods 
 

        //--------------------------------------------------------------------- 
        //
        //  Private Methods
        //
        //---------------------------------------------------------------------- 

        #region Private Methods 
 
        /// 
        /// Connects the hosted visual on a channel if necessary. 
        /// 
        private void EnsureHostedVisualConnected(DUCE.Channel channel)
        {
            // 
            // Conditions for connecting VisualTarget to Host Visual:-
            // 1. The channel on which we are rendering should not be synchronous. This 
            //    scenario is not supported currently. 
            // 2. VisualTarget should not be null.
            // 3. They should not be already connected. 
            //
            if (!(channel.IsSynchronous)
                && _target != null
                && !_connectedChannels.Contains(channel) 
                && !channel.IsLayeredWindowChannel)
            { 
                Debug.Assert(IsOnChannel(channel)); 

                DUCE.ResourceHandle targetsHandle = DUCE.ResourceHandle.Null; 

                bool doDuplication = true;

                // 
                // If HostVisual and VisualTarget are on same thread, then we just addref
                // VisualTarget. Otherwise, if on different threads, then we duplicate 
                // VisualTarget onto Hostvisual's channel. 
                //
                if (_target.CheckAccess()) 
                {
                    Debug.Assert(_target._contentRoot.IsOnChannel(channel));
                    Debug.Assert(_target.OutOfBandChannel == MediaContext.CurrentMediaContext.OutOfBandChannel);
                    bool created = _target._contentRoot.CreateOrAddRefOnChannel(channel, VisualTarget.s_contentRootType); 
                    Debug.Assert(!created);
                    targetsHandle = _target._contentRoot.GetHandle(channel); 
                } 
                else
                { 
                    //
                    // Duplicate the target's handle onto our channel.
                    //
                    // We must wait synchronously for the _targets Dispatcher to call 
                    // back and do handle duplication. We can't do handle duplication
                    // on this thread because access to the _target CompositionNode 
                    // is not synchronized. If we duplicated here, we could potentially 
                    // corrupt the _target OutOfBandChannel or the CompositionNode
                    // MultiChannelResource. We have to wait synchronously because 
                    // we need the resulting duplicated handle to hook up as a child
                    // to this HostVisual.
                    //
 
                    ArrayList parameters = new ArrayList(2);
                    parameters.Add(channel); 
                    parameters.Add((object)MediaSystem.GenerationId); 

                    object returnValue = _target.Dispatcher.Invoke( 
                        DispatcherPriority.Normal,
                        TimeSpan.FromMilliseconds(1000),
                        new DispatcherOperationCallback(DoHandleDuplication),
                        parameters 
                        );
 
                    // 
                    // Duplication and flush is complete, we can resume processing
                    // Only if the Invoke succeeded will we have a handle returned. 
                    //
                    if (returnValue != null)
                    {
                        targetsHandle = (DUCE.ResourceHandle)returnValue; 
                    }
                    else 
                    { 
                        // The Invoke didn't complete
                        doDuplication = false; 
                    }
                }

                if (doDuplication) 
                {
                    if (!targetsHandle.IsNull) 
                    { 
                        using (CompositionEngineLock.Acquire())
                        { 
                            DUCE.CompositionNode.InsertChildAt(
                                _proxy.GetHandle(channel),
                                targetsHandle,
                                0, 
                                channel);
                        } 
 
                        _connectedChannels.Add(channel);
 
                        //
                        // Indicate that that content composition root has been
                        // connected, this needs to be taken into account to
                        // properly manage children of this visual. 
                        //
 
                        SetFlags(channel, true, VisualProxyFlags.IsContentNodeConnected); 
                    }
                } 
                else
                {
                    //
                    // We didn't get a handle, because _target belongs to a 
                    // different thread, and the Invoke operation failed. We can't do
                    // anything except try again in the next render pass. We can't 
                    // call Invalidate during the render pass because it pushes up 
                    // flags that are being modified within the render pass, so get
                    // the local Dispatcher to do it for us later. 
                    //
                    Dispatcher.BeginInvoke(
                        DispatcherPriority.Normal,
                        (DispatcherOperationCallback)delegate(object args) 
                        {
                            Invalidate(); 
                            return null; 
                        },
                        null 
                        );
                }
            }
        } 

 
        ///  
        /// Disconnects the hosted visual on all channels we have
        /// connected it to. 
        /// 
        private void DisconnectHostedVisualOnAllChannels()
        {
            foreach (DUCE.Channel channel in _connectedChannels) 
            {
                DisconnectHostedVisual( 
                    channel, 
                    /* removeChannelFromCollection */ false);
            } 

            _connectedChannels.Clear();
        }
 

        ///  
        /// Disconnects the hosted visual on a channel. 
        /// 
        private void DisconnectHostedVisual( 
            DUCE.Channel channel,
            bool removeChannelFromCollection)
        {
            if (_target != null && _connectedChannels.Contains(channel)) 
            {
                DUCE.CompositionNode.RemoveChild( 
                    _proxy.GetHandle(channel), 
                    _target._contentRoot.GetHandle(channel),
                    channel 
                    );

                //
                // Release the targets handle. If we had duplicated the handle, 
                // then this removes the duplicated handle, otherwise just decrease
                // the ref count for VisualTarget. 
                // 

                _target._contentRoot.ReleaseOnChannel(channel); 

                SetFlags(channel, false, VisualProxyFlags.IsContentNodeConnected);

                if (removeChannelFromCollection) 
                {
                    _connectedChannels.Remove(channel); 
                } 
            }
        } 


        /// 
        /// Invalidate this visual. 
        /// 
        private void Invalidate() 
        { 
            SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty);
 
            PropagateChangedFlags();
        }

        #endregion Private Methods 

 
        //--------------------------------------------------------------------- 
        //
        //  Private Fields 
        //
        //---------------------------------------------------------------------

        #region Private Fields 

        private EventHandler _propagateState; 
        private VisualTarget.HostState _state; 

        ///  
        /// The hosted visual target.
        /// 
        /// 
        /// This field is free-threaded and should be accessed from under a lock. 
        /// 
        private VisualTarget _target; 
 
        /// 
        /// The channels we have marshalled the visual target composition root. 
        /// 
        /// 
        /// This field is free-threaded and should be accessed from under a lock.
        ///  
        private List _connectedChannels = new List();
 
        #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