HwndSource.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 / Core / System / Windows / InterOp / HwndSource.cs / 4 / HwndSource.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2004
//
//  File: HwndSource.cs 
//-----------------------------------------------------------------------------
 
using System.Collections; 
using System.Collections.Generic;
using System.Threading; 
using System.Windows.Threading;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Interop; 
using System.Runtime.InteropServices;
using MS.Win32; 
using MS.Utility; 
using MS.Internal;
using MS.Internal.PresentationCore;                        // SecurityHelper 
using Microsoft.Win32;
using System.Diagnostics;
using System.ComponentModel;
using System; 
using System.Security;
using System.Security.Permissions; 
using System.IO; 

using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;

#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
namespace System.Windows.Interop
{ 
    ///  
    ///     The HwndSource class presents content within a Win32 HWND.
    ///  
    public class HwndSource : PresentationSource, IDisposable, IWin32Window, IKeyboardInputSink
    {
        /// 
        ///     Critical: This code calls into RegisterWindowMesssage which is critical 
        ///     TreatAsSafe: This is safe to call as no external parameters are taken in
        ///  
        [SecurityCritical,SecurityTreatAsSafe] 
        static HwndSource()
        { 
            _threadSlot = Thread.AllocateDataSlot();
            _msgEnableCharMessages = UnsafeNativeMethods.RegisterWindowMessage("HwndSourceEnableCharMessages");
        }
 
        /// 
        ///    Constructs an instance of the HwndSource class that will always resize to its content size. 
        ///  
        /// 
        ///     The Win32 class styles for this window. 
        /// 
        /// 
        ///     The Win32 styles for this window.
        ///  
        /// 
        ///     The extended Win32 styles for this window. 
        ///  
        /// 
        ///     The position of the left edge of this window. 
        /// 
        /// 
        ///     The position of the upper edge of this window.
        ///  
        /// 
        ///     The name of this window. 
        ///  
        /// 
        ///     The Win32 window that should be the parent of this window. 
        /// 
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        /// 
        ///     Added a demand - so that this API does not work in InternetZone. 
        ///     Critical: This accesses critical code Initialize 
        ///     PublicOK: This code has a demand which will ensure that it does
        ///     not work in partial trust without the correct permissions 
        /// 
        [SecurityCritical]
        public HwndSource(
            int classStyle, 
            int style,
            int exStyle, 
            int x, 
            int y,
            string name, 
            IntPtr parent)
        {
            SecurityHelper.DemandUIWindowPermission();
 
            HwndSourceParameters param = new HwndSourceParameters(name);
            param.WindowClassStyle = classStyle; 
            param.WindowStyle = style; 
            param.ExtendedWindowStyle = exStyle;
            param.SetPosition(x, y); 
            param.ParentWindow = parent;
            Initialize(param);
        }
 
        /// 
        ///    Constructs an instance of the HwndSource class. This version requires an 
        ///    explicit width and height be sepecified. 
        /// 
        ///  
        ///     The Win32 class styles for this window.
        /// 
        /// 
        ///     The Win32 styles for this window. 
        /// 
        ///  
        ///     The extended Win32 styles for this window. 
        /// 
        ///  
        ///     The position of the left edge of this window.
        /// 
        /// 
        ///     The position of the upper edge of this window. 
        /// 
        ///  
        ///     The width of this window. 
        /// 
        ///  
        ///     The height of this window.
        /// 
        /// 
        ///     The name of this window. 
        /// 
        ///  
        ///     The Win32 window that should be the parent of this window. 
        /// 
        ///  
        ///     Indicates that HwndSource should include the non-client area
        ///     of the hwnd when it calls the Layout Manager
        /// 
        ///  
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        ///  
        ///     Added a demand - so that this API does not work in InternetZone.
        ///     Critical: This acceses critical code Initialize 
        ///     PublicOK: This code has a demand which will ensure that it does
        ///     not work in partial trust without the correct permissions
        /// 
        [SecurityCritical] 
        public HwndSource(int classStyle,
                          int style, 
                          int exStyle, 
                          int x,
                          int y, 
                          int width,
                          int height,
                          string name,
                          IntPtr parent, 
                          bool adjustSizingForNonClientArea)
        { 
            SecurityHelper.DemandUIWindowPermission(); 

            HwndSourceParameters parameters = new HwndSourceParameters(name, width, height); 
            parameters.WindowClassStyle = classStyle;
            parameters.WindowStyle = style;
            parameters.ExtendedWindowStyle = exStyle;
            parameters.SetPosition(x, y); 
            parameters.ParentWindow = parent;
            parameters.AdjustSizingForNonClientArea = adjustSizingForNonClientArea; 
            Initialize(parameters); 
        }
 
        /// 
        ///    Constructs an instance of the HwndSource class. This version requires an
        ///    explicit width and height be sepecified.
        ///  
        /// 
        ///     The Win32 class styles for this window. 
        ///  
        /// 
        ///     The Win32 styles for this window. 
        /// 
        /// 
        ///     The extended Win32 styles for this window.
        ///  
        /// 
        ///     The position of the left edge of this window. 
        ///  
        /// 
        ///     The position of the upper edge of this window. 
        /// 
        /// 
        ///     The width of this window.
        ///  
        /// 
        ///     The height of this window. 
        ///  
        /// 
        ///     The name of this window. 
        /// 
        /// 
        ///     The Win32 window that should be the parent of this window.
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///  
        /// 
        ///     Added a demand - so that this API does not work in InternetZone. 
        ///     Critical: This accesses critical code Initialize
        ///     PublicOK: This code has a demand which will ensure that it does
        ///     not work in partial trust without the correct permissions
        ///  
        [SecurityCritical]
        public HwndSource( 
            int classStyle, 
            int style,
            int exStyle, 
            int x,
            int y,
            int width,
            int height, 
            string name,
            IntPtr parent) 
        { 
            SecurityHelper.DemandUIWindowPermission();
 
            HwndSourceParameters parameters = new HwndSourceParameters(name, width, height);
            parameters.WindowClassStyle = classStyle;
            parameters.WindowStyle = style;
            parameters.ExtendedWindowStyle = exStyle; 
            parameters.SetPosition(x, y);
            parameters.ParentWindow = parent; 
            Initialize(parameters); 
        }
 
        /// 
        ///    HwndSource Ctor
        /// 
        ///  parameter block  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///  
        /// 
        ///     Critical: This acceses critical code Initialize 
        /// 
        [SecurityCritical]
        [UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
        public HwndSource(HwndSourceParameters parameters) 
        {
            Initialize(parameters); 
        } 
        /// 
        ///    HwndSource Ctor 
        /// 
        ///  parameter block 
        /// 
        ///     Critical: This code access critical (HwndMouseInputProvider, HwndKeyboardInputProvider 
        ///     ,HwndStylusInputProvider and the various hooks)objects and creates the
        ///     providers under elevation. 
        ///  
        [SecurityCritical]
        private void Initialize(HwndSourceParameters parameters) 
        {
            _mouse = new SecurityCriticalDataClass(new HwndMouseInputProvider(this));
            _keyboard = new SecurityCriticalDataClass(new HwndKeyboardInputProvider(this));
            _layoutHook = new HwndWrapperHook(LayoutFilterMessage); 
            _inputHook = new HwndWrapperHook(InputFilterMessage);
            _hwndTargetHook = new HwndWrapperHook(HwndTargetFilterMessage); 
 
            _publicHook = new HwndWrapperHook(PublicHooksFilterMessage);
 
            // When processing WM_SIZE, LayoutFilterMessage must be invoked before
            // HwndTargetFilterMessage. This way layout will be updated before resizing
            // HwndTarget, resulting in single render per resize. This means that
            // layout hook should appear before HwndTarget hook in the wrapper hooks 
            // list. If this is done the other way around, first HwndTarget resize will
            // force re-render, then layout will be updated according to the new size, 
            // scheduling another render. 
            HwndWrapperHook[] wrapperHooks = { _hwndTargetHook, _layoutHook, _inputHook, null };
 
            if(null != parameters.HwndSourceHook)
            {
                _hooks = new ArrayList(8);
                _hooks.Insert(0, parameters.HwndSourceHook); 
                wrapperHooks[3] = _publicHook;
            } 
 
            // A window must be marked WS_EX_LAYERED if (and only if):
            // 1) it is not a child window 
            //    -- AND --
            // 2) a color-key is specified
            // 3) or an opacity other than 1.0 is specified
            // 4) or per-pixel alpha is requested. 
            if((parameters.WindowStyle & NativeMethods.WS_CHILD) == 0 &&
               ( //parameters.ColorKey != null || 
                 //!MS.Internal.DoubleUtil.AreClose(parameters.Opacity, 1.0) || 
                parameters.UsesPerPixelOpacity))
            { 
                parameters.ExtendedWindowStyle |= NativeMethods.WS_EX_LAYERED;
            }
            else
            { 
                parameters.ExtendedWindowStyle &= (~NativeMethods.WS_EX_LAYERED);
            } 
 

            _constructionParameters = parameters; 
            _hwndWrapper = new HwndWrapper(parameters.WindowClassStyle,
                                       parameters.WindowStyle,
                                       parameters.ExtendedWindowStyle,
                                       parameters.PositionX, 
                                       parameters.PositionY,
                                       parameters.Width, 
                                       parameters.Height, 
                                       parameters.WindowName,
                                       parameters.ParentWindow, 
                                       wrapperHooks);

            _hwndTarget = new HwndTarget(_hwndWrapper.Handle);
            //_hwndTarget.ColorKey = parameters.ColorKey; 
            //_hwndTarget.Opacity = parameters.Opacity;
            _hwndTarget.UsesPerPixelOpacity = parameters.UsesPerPixelOpacity; 
            if(_hwndTarget.UsesPerPixelOpacity) 
            {
                _hwndTarget.BackgroundColor = Colors.Transparent; 

                // Prevent this window from being themed.
                UnsafeNativeMethods.CriticalSetWindowTheme(new HandleRef(this, _hwndWrapper.Handle), "", "");
            } 
            _constructionParameters = null;
 
            if (!parameters.HasAssignedSize) 
                _sizeToContent = SizeToContent.WidthAndHeight;
            _adjustSizingForNonClientArea = parameters.AdjustSizingForNonClientArea; 

            // Listen to the UIContext.Disposed event so we can clean up.
            // The HwndTarget cannot work without a MediaContext which
            // is disposed when the UIContext is disposed.  So we need to 
            // dispose the HwndTarget and also never use it again (to
            // paint or process input).  The easiest way to do this is to just 
            // dispose the HwndSource at the same time. 
            _weakShutdownHandler = new WeakEventDispatcherShutdown(this, this.Dispatcher);
 
            // Listen to the HwndWrapper.Disposed event so we can clean up.
            // The HwndTarget cannot work without a live HWND, and since
            // the HwndSource represents an HWND, we make sure we dispose
            // ourselves if the HWND is destroyed out from underneath us. 
            _hwndWrapper.Disposed += new EventHandler(OnHwndDisposed);
 
            _stylus = new SecurityCriticalDataClass(new HwndStylusInputProvider(this)); 

            // WM_APPCOMMAND events are handled thru this. 
            _appCommand = new SecurityCriticalDataClass(new HwndAppCommandInputProvider(this));

            // Register the top level source with the ComponentDispatcher.
            if (0 == ((uint)parameters.WindowStyle & NativeMethods.WS_CHILD)) 
            {
                // This code path only gets executed in the non browser hosted case 
                // because in the browser hosted case the app window is child window 
                _weakPreprocessMessageHandler = new WeakEventPreprocessMessage(this);
            } 
            AddSource();

            // Register dropable window.
            // The checking CallerHasPermissionWithAppDomainOptimization will call RegisterDropTarget 
            // safely without the security exception in case of no unmanaged code permission.
            // So RegisterDropTarget will be called safely in case of having the unmanged code permission. 
            // Otherwise, the security exception cause System.Printing to be instatiated which will 
            // load system.drawing module.
            if (_hwndWrapper.Handle != IntPtr.Zero && 
                SecurityHelper.CallerHasPermissionWithAppDomainOptimization(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)))
            {
                // This call is safe since DragDrop.RegisterDropTarget is checking the unmanged
                // code permission. 
                DragDrop.RegisterDropTarget(_hwndWrapper.Handle);
                _registeredDropTargetCount++; 
            } 
        }
 
        /// 
        ///     Disposes the object
        /// 
        /// 
        /// This API is not available in Internet Zone.
        /// 
        public void Dispose() 
        {
            Dispose(true); 
            GC.SuppressFinalize(this);
        }

        ///  
        ///     Adds a hook that gets called for every window message.
        ///  
        ///  
        ///     The hook to add.
        ///  
        ///
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///
        /// 
        /// Critical - uses a critical field.
        /// PublicOK - as there's a demand. 
        /// 
        [SecurityCritical ]
        public void AddHook(HwndSourceHook hook) 
        {
            SecurityHelper.DemandUIWindowPermission();

            CheckDisposed(true); 

            if(_hooks == null) 
            { 
                _hooks = new ArrayList(8);
                _hwndWrapper.AddHook(_publicHook); 
            }
            _hooks.Insert(0, hook);
        }
 
        /// 
        ///     Removes a hook that was previously added. 
        ///  
        /// 
        ///     The hook to remove. 
        /// 
        ///
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        /// 
        ///
        /// Critical - accesses a crtical field - _publicHook 
        /// PublicOK - performs a demand. 
        ///
        [SecurityCritical ] 
        public void RemoveHook(HwndSourceHook hook)
        {
            SecurityHelper.DemandUIWindowPermission();
 
            //this.VerifyAccess();
 
            if(_hooks != null) 
            {
                _hooks.Remove(hook); 
                if(_hooks.Count == 0)
                {
                    _hooks = null;
                    _hwndWrapper.RemoveHook(_publicHook); 
                }
            } 
        } 

        ///  
        /// GetInputProvider - Given a InputDevice, returns corresponding Provider
        /// 
        /// InputDevice for which we need InputProvider
        /// InputProvider, if known 
        ///
        /// This API is not available in Internet Zone. 
        /// 
        /// 
        ///     Critical: This code accesses and returns critical data *providers* 
        /// 
        [SecurityCritical]
        internal override IInputProvider GetInputProvider(Type inputDevice)
        { 
            if (inputDevice == typeof(MouseDevice))
                return (_mouse    != null ?    _mouse.Value : null); 
 
            if (inputDevice == typeof(KeyboardDevice))
                return (_keyboard != null ? _keyboard.Value : null); 

            if (inputDevice == typeof(StylusDevice))
                return (_stylus   != null ?   _stylus.Value : null);
 
            return null;
        } 
 
        /// 
        ///     Announces when this source is disposed. 
        /// 
        public event EventHandler Disposed;

        ///  
        ///     Announces when the SizeToContent property changes on this source.
        ///  
        public event EventHandler SizeToContentChanged; 

        ///  
        ///     Whether or not the object is disposed.
        /// 
        public override bool IsDisposed {get {return _isDisposed;}}
 
        /// 
        /// The Root Visual for this window. If it is a UIElement 
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        /// 
        /// 
        ///     Critical: This code sets a rootvisual which is risky to do because
        ///     it can destabilize assumptions made in popup code 
        ///     PublicOK: The getter is safe and the setter has a link demand to block unwarrented
        ///     public use 
        ///  
        public override Visual RootVisual
        { 
            [SecurityCritical]
            get
            {
                if (_isDisposed) 
                    return null;
                return (_rootVisual.Value); 
            } 
            [SecurityCritical]
            [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)] 
            set
            {
                CheckDisposed(true);
 
                RootVisualInternal = value;
            } 
        } 

        ///  
        /// Critical: Acceses KeyboardInputProvider which is considered as critical data
        /// also it can be used to set root visual which is deemed as an unsafe operation
        /// 
        private Visual RootVisualInternal 
        {
            [SecurityCritical] 
            set 
            {
                if (_rootVisual.Value != value) 
                {
                    Visual oldRoot = _rootVisual.Value;

                    if(value != null) 
                    {
                        _rootVisual.Value = value; 
 
                        if(_rootVisual.Value is UIElement)
                        { 
                            ((UIElement)(_rootVisual.Value)).LayoutUpdated += new EventHandler(OnLayoutUpdated);
                        }

                        if (_hwndTarget != null && _hwndTarget.IsDisposed == false) 
                        {
                            _hwndTarget.RootVisual = _rootVisual.Value; 
                        } 

                        UIElement.PropagateResumeLayout(null, value); 
                    }
                    else
                    {
                        _rootVisual.Value = null; 
                        if (_hwndTarget != null && !_hwndTarget.IsDisposed)
                        { 
                            _hwndTarget.RootVisual = null; 
                        }
                    } 

                    if(oldRoot != null)
                    {
                        if(oldRoot is UIElement) 
                        {
                            ((UIElement)oldRoot).LayoutUpdated -= new EventHandler(OnLayoutUpdated); 
                        } 

                        UIElement.PropagateSuspendLayout(oldRoot); 
                    }

                    RootChanged(oldRoot, _rootVisual.Value);
 
                    if (IsLayoutActive() == true)
                    { 
                        // Call the helper method SetLayoutSize to set Layout's size 
                        SetLayoutSize();
 
                        // Post the firing of ContentRendered as Input priority work item so that ContentRendered will be
                        // fired after render query empties.
                        this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(FireContentRendered), this);
                    } 
                    else
                    { 
                        // Even though layout won't run (the root visual is either null or not 
                        // a UIElement), the hit-test results will certainly have changed.
                        InputManager.SafeCurrentNotifyHitTestInvalidated(); 
                    }

                    // It is possible that someone would have closed the window in one of the
                    // previous callouts - such as during RootChanged or during the layout 
                    // we syncronously invoke.  In such cases, the state of this object would
                    // have been torn down.  We just need to protect against that. 
                    if(_keyboard != null) 
                    {
                        _keyboard.Value.OnRootChanged(oldRoot, _rootVisual.Value); 
                    }
                }
            }
        } 

        ///  
        ///     Returns the HwndSource that corresponds to the specified window. 
        /// 
        /// The window. 
        /// The source that corresponds to the specified window.
        ///
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        /// 
        /// 
        ///     Critical: This information is not ok to expose since this HwndSource 
        ///     is deemed critical to expose 
        ///     PublicOK: There is a demand on this method that prevents this
        ///     from working in partial trust unless you have the right permissions. 
        /// 
        [SecurityCritical]
        public static HwndSource FromHwnd(IntPtr hwnd)
        { 
            SecurityHelper.DemandUIWindowPermission();
            return CriticalFromHwnd(hwnd); 
        } 

        ///  
        ///    Critical: This code extracts the HwndSource for an HWND
        ///    This function is only for internal consumption
        /// 
        [SecurityCritical] 
        internal static HwndSource CriticalFromHwnd(IntPtr hwnd)
        { 
            if (hwnd == IntPtr.Zero) 
            {
                throw new ArgumentException(SR.Get(SRID.NullHwnd)); 
            }
            HwndSource hwndSource = null;
            foreach (PresentationSource source in PresentationSource.CriticalCurrentSources)
            { 
                HwndSource test = source as HwndSource;
                if (test != null && test.CriticalHandle == hwnd) 
                { 
                    // Don't hand out a disposed source.
                    if (!test.IsDisposed) 
                        hwndSource = test;
                    break;
                }
            } 
            return hwndSource;
        } 
 

        ///  
        ///     The visual manager for the visuals being presented in the source.
        ///     Type-specific version of the CompositionTarget property for this source.
        /// 
        ///  
        ///     Critical: Accesses hwndTarget and returns it
        ///     PublicOk: Protected by a LinkDemand 
        ///  
        public new HwndTarget CompositionTarget
        { 
            [SecurityCritical]
            [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
            get
            { 
                if (_isDisposed)
                    return null; 
 
                // Even though we created the HwndTarget, it can get disposed out from
                // underneath us. 
                if (_hwndTarget!= null && _hwndTarget.IsDisposed == true)
                {
                    return null;
                } 

                return _hwndTarget; 
            } 
        }
 
        /// 
        ///     Returns visual target for this source.
        /// 
        ///  
        ///     Critical: calls get_CompositionTarget() and returns its value.
        ///  
        [SecurityCritical] 
        protected override CompositionTarget GetCompositionTargetCore()
        { 
            return CompositionTarget;
        }

        ///  
        ///     Event invoked when the layout causes the HwndSource to resize automatically.
        ///  
        public event AutoResizedEventHandler AutoResized; 

        ///  
        /// Handler for LayoutUpdated event of a rootVisual.
        /// 
        /// 
        ///     Critical: This code causes resize of window and accesses HwndTarget 
        /// 
        [SecurityCritical] 
        private void OnLayoutUpdated(object obj, EventArgs args) 
        {
            UIElement root = _rootVisual.Value as UIElement; 

            if(root != null)
            {
                Size newSize = root.RenderSize; 
                if (   _previousSize == null
                    || !DoubleUtil.AreClose(_previousSize.Value.Width, newSize.Width) 
                    || !DoubleUtil.AreClose(_previousSize.Value.Height, newSize.Height)) 
                {
                    // We should update _previousSize, even if the hwnd is not 
                    // sizing to content.  This fixes the scenario where:
                    //
                    // 1) hwnd is sized to content to say a, b
                    // 2) hwnd is resize to a bigger size 
                    // 3) hwnd is sized to content to a, b again
                    _previousSize = newSize; 
 
                    //
                    // Don't resize while the Window is in Minimized mode. 
                    //
                    if (_sizeToContent != SizeToContent.Manual && !_isWindowInMinimizeState )
                    {
                        Resize(newSize); 
                    }
                } 
            } 
        }
 
        /// 
        /// This is called when LayoutManager was updated and its size (the layout size of top element) changed.
        /// Ask LayoutManager.Size to see what the new value is.
        ///  
        /// 
        ///     Critical: This code causes resize of window and accesses HwndTarget 
        ///     TreatAsSafe: In RBW the resize values are clamped also one cannot construct or get to a HwndSource in partial trust 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private void Resize(Size newSize)
        {
            try
            { 
                _myOwnUpdate = true;
 
                if (IsUsable) 
                {
                    // Gather the new client dimensions 
                    Point convertedPt = _hwndTarget.TransformToDevice.Transform(new Point(newSize.Width, newSize.Height));
                    int frameWidth = 0;
                    int frameHeight = 0;
 
                    // If we're here, and it is the Window case (_adjustSizingForNonClientArea == true)
                    // we get the size which includes the outside size of the window.  For browser case, 
                    // we don't support SizeToContent, so we don't take care of this condition. 
                    // For non-Window cases, we need to calculate the outside size of the window
                    // 
                    // For windows with UsesPerPixelOpacity, we force the client to
                    // fill the window, so we don't need to add in any frame space.
                    //
                    if (_adjustSizingForNonClientArea == false && !UsesPerPixelOpacity) 
                    {
                        // Gather current client and frame dimensions from the window 
                        NativeMethods.RECT oldClientRect = new NativeMethods.RECT(0, 0, 0, 0); 
                        SafeNativeMethods.GetClientRect(new HandleRef(this,_hwndWrapper.Handle), ref oldClientRect);
                        NativeMethods.RECT oldFrameRect = new NativeMethods.RECT(0, 0, 0, 0); 
                        SafeNativeMethods.GetWindowRect(new HandleRef(this,_hwndWrapper.Handle), ref oldFrameRect);

                        frameWidth = (oldFrameRect.right - oldFrameRect.left) - (oldClientRect.right - oldClientRect.left) ;
                        frameHeight = (oldFrameRect.bottom - oldFrameRect.top) - (oldClientRect.bottom - oldClientRect.top); 
                    }
 
                    // Add the difference between the client and frame dimensions (i.e. the window chrome) to the new client dimensions 
                    RoundDeviceSize(ref convertedPt);
                    int newWidth = frameWidth + (int)convertedPt.X; 
                    int newHeight = frameHeight + (int)convertedPt.Y;

                    // Set the new frame size
                    bool set = UnsafeNativeMethods.SetWindowPos(new HandleRef(this,_hwndWrapper.Handle), new HandleRef(null,IntPtr.Zero), 0, 0, newWidth, newHeight, NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE); 

                    if (AutoResized != null) 
                    { 
                        AutoResized(this, new AutoResizedEventArgs(newSize));
                    } 
                }
            }
            finally
            { 
                _myOwnUpdate = false;
            } 
        } 

        // If the root element has Pixel snapping enabled, round the window size to the 
        // nearest int.  Otherwise round the size up to the next int.
        private void RoundDeviceSize(ref Point size)
        {
            UIElement root = _rootVisual.Value as UIElement; 
            if (root != null && root.SnapsToDevicePixels)
            { 
                size = new Point(DoubleUtil.DoubleToInt(size.X), DoubleUtil.DoubleToInt(size.Y)); 
            }
            else 
            {
                size = new Point(Math.Ceiling(size.X), Math.Ceiling(size.Y));
            }
        } 

        ///  
        /// Returns the hwnd handle to the window. 
        /// 
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///
        /// 
        ///     Critical:This is not safe to expose in internet zone, it returns a window handle 
        ///     PublicOK: There exists a demand on this code
        ///  
        public IntPtr Handle 
        {
            [SecurityCritical] 
            get
            {
                SecurityHelper.DemandUIWindowPermission();
                return CriticalHandle; 
            }
        } 
 
        /// 
        ///     Critical:Internal helper to retrieve handle for security purposes only Please 
        ///     DO NOT USE THIS TO  EXPOSE HANDLE TO OUTSIDE WORLD
        /// 
        internal IntPtr CriticalHandle
        { 
            [FriendAccessAllowed]
            [SecurityCritical] 
            get 
            {
                if (null != _hwndWrapper) 
                    return _hwndWrapper.Handle;
                return IntPtr.Zero;
            }
        } 

        ///  
        ///     Critical: returns the critical _hwndWrapper. 
        /// 
        internal HwndWrapper HwndWrapper 
        {
            [SecurityCritical]
            get { return _hwndWrapper; }
        } 

        // Return whether this presentation source has capture. 
        ///  
        ///     Critical: calls CriticalHandle
        ///     TreatAsSafe: Returning whether a presentation source has capture is considered safe. 
        /// 
        internal bool HasCapture
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                IntPtr capture = SafeNativeMethods.GetCapture(); 

                return ( capture == CriticalHandle ); 
            }
        }

        /// 
        ///     Critical - accesses _hwndWrapper.
        ///     TreatAsSafe - checking for null is considered safe. 
        /// 
        internal bool IsHandleNull
        { 
            [SecurityCritical, SecurityTreatAsSafe ]
            get
            {
                return _hwndWrapper.Handle == IntPtr.Zero ; 
            }
        } 
 
        /// 
        /// Returns the hwnd handle to the window. 
        /// 
        public HandleRef CreateHandleRef()
        {
            return new HandleRef(this,Handle); 
        }
 
 
        /// 
        /// SizeToContent on HwndSource 
        /// 
        /// 
        /// The default value is SizeToContent.Manual
        ///  
        public SizeToContent SizeToContent
        { 
            get 
            {
                CheckDisposed(true); 
                return _sizeToContent;
            }

            set 
            {
                CheckDisposed(true); 
 
                if (IsValidSizeToContent(value) != true)
                { 
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(SizeToContent));
                }

                if (_sizeToContent == value) 
                {
                    return; 
                } 

                _sizeToContent = value; 

                // we only raise SizeToContentChanged when user interaction caused the change;
                // if a developer goes directly to HwndSource and sets SizeToContent, we will
                // not notify the wrapping Window 

                if (IsLayoutActive() == true) 
                { 
                    // Call the helper method SetLayoutSize to set Layout's size
                    SetLayoutSize(); 
                }
            }
        }
 
        /// 
        ///     Critical: This code elevates to access hwndtarget 
        ///     TreatAsSafe: ok to expose 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private bool IsLayoutActive()
        {

            if ((_rootVisual.Value is UIElement) && _hwndTarget!= null && _hwndTarget.IsDisposed == false) 
            {
                return true; 
            } 

            return false; 
        }

        /// 
        /// This is the helper method that sets Layout's size basing it on 
        /// the current value of SizeToContent.
        ///  
        /// 
        ///  TreatAsSafe: This API could be public in terms of security.
        ///  It does three calls to UnsafeNativeMethods all in a safe way 
        ///  Critical: Makes 3 calls to UnsafeNativeMethods
        ///
        [SecurityCritical, SecurityTreatAsSafe]
        private void SetLayoutSize() 
        {
            Debug.Assert(_hwndTarget!= null, "HwndTarget is null"); 
            Debug.Assert(_hwndTarget.IsDisposed == false, "HwndTarget is disposed"); 

            UIElement rootUIElement = null; 
            rootUIElement = _rootVisual.Value as UIElement;
            if (rootUIElement == null) return;

            // [....] - 11/01/2005 
            // InvalidateMeasure() call is necessary in the following scenario
            // 
            // Window w = new Window(); 
            // w.Measure(new Size(x,y));
            // w.Width = x; 
            // w.Height = y;
            // w.Show()
            //
            // In the above scenario, the Measure call from SetLayoutSize will be opt out 
            // and window will not receive the MeasureOverride call.  As such, the hwnd min/max
            // restrictions will not be applied since MeasureOverride did not happen after hwnd 
            // creation.  Thus, we call InvalidatMeasure() to ensure MeasureOverride call on 
            // Window after hwnd creation.
 
            rootUIElement.InvalidateMeasure();

            bool etwEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal);
            int  ctxHashCode = 0; 

            if (_sizeToContent == SizeToContent.WidthAndHeight) 
            { 
                //setup constraints for measure-to-content
                Size sz = new Size(double.PositiveInfinity, double.PositiveInfinity); 

                if (etwEnabled)
                {
                    ctxHashCode = this.Dispatcher.GetHashCode(); 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 
                }
 
                rootUIElement.Measure(sz);

                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 
                }
 
                rootUIElement.Arrange(new Rect(new Point(), rootUIElement.DesiredSize));

                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent); 
                }
            } 
            else
            {
                // GetSizeFromHwnd sets either the outside size or the client size of the hwnd based on
                // _adjustSizeingForNonClientArea flag in logical units. 
                Size sizeFromHwndLogicalUnits = GetSizeFromHwnd();
                Size sz = new Size( 
                        (_sizeToContent == SizeToContent.Width ? double.PositiveInfinity : sizeFromHwndLogicalUnits.Width), 
                        (_sizeToContent == SizeToContent.Height ? double.PositiveInfinity : sizeFromHwndLogicalUnits.Height));
 
                if (etwEnabled)
                {
                    ctxHashCode = this.Dispatcher.GetHashCode();
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 
                } 

                rootUIElement.Measure(sz); 

                if (etwEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent); 

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 
                } 

                if (_sizeToContent == SizeToContent.Width) sz = new Size(rootUIElement.DesiredSize.Width, sizeFromHwndLogicalUnits.Height); 
                else if(_sizeToContent == SizeToContent.Height) sz = new Size(sizeFromHwndLogicalUnits.Width, rootUIElement.DesiredSize.Height);
                else sz = sizeFromHwndLogicalUnits;

                rootUIElement.Arrange(new Rect(new Point(), sz)); 

                if (etwEnabled) 
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent);
                }
            }
            rootUIElement.UpdateLayout(); 
        }
 
        // ///  
        // ///     Specifies the color to display as transparent.
        // ///  
        // /// 
        // ///     Use null to indicate that no color should be transparent.
        // /// 
        // public Nullable ColorKey 
        // {
        //     get 
        //     { 
        //         CheckDisposed(true);
        // 
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed
        //         if(_hwndTarget != null)
        //         {
        //             return _hwndTarget.ColorKey; 
        //         }
        //         else 
        //         { 
        //             return null;
        //         } 
        //     }
        //
        //     set
        //     { 
        //         CheckDisposed(true);
        // 
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed 
        //         if(_hwndTarget != null)
        //         { 
        //             _hwndTarget.ColorKey = value;
        //         }
        //     }
        // } 

        // ///  
        // ///     Specifies the constant opacity to apply to the window. 
        // /// 
        // ///  
        // ///     The valid values range from [0..1].  Values outside of this range are clamped.
        // /// 
        // public double Opacity
        // { 
        //     get
        //     { 
        //         CheckDisposed(true); 
        //
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed 
        //         if(_hwndTarget != null)
        //         {
        //             return _hwndTarget.Opacity;
        //         } 
        //         else
        //         { 
        //             return 1.0; 
        //         }
        //     } 
        //
        //     set
        //     {
        //         CheckDisposed(true); 
        //
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed 
        //         if(_hwndTarget != null) 
        //         {
        //             _hwndTarget.Opacity = value; 
        //         }
        //     }
        // }
 
        /// 
        ///     Specifies whether or not the per-pixel opacity of the window content 
        ///     is respected. 
        /// 
        ///  
        ///     By enabling per-pixel opacity, the system will no longer draw the non-client area.
        /// 
        /// 
        ///     Critical: Because it accesses _hwndTarget 
        ///     PublicOK: We don't pass it out; it is just used to query UsesPerPixelOpacity
        ///  
        public bool UsesPerPixelOpacity 
        {
            [SecurityCritical] 
            get
            {
                CheckDisposed(true);
 
                HwndTarget hwndTarget = CompositionTarget; // checks for disposed
                if(_hwndTarget != null) 
                { 
                    return _hwndTarget.UsesPerPixelOpacity;
                } 
                else
                {
                    return false;
                } 
            }
 
/* Not allowing this to change at run-time yet. 
            [SecurityCritical]
            set 
            {
                CheckDisposed(true);

                HwndTarget hwndTarget = CompositionTarget; // checks for disposed 
                if(_hwndTarget != null)
                { 
                    _hwndTarget.UsesPerPixelOpacity = value; 
                }
            } 
*/
        }

        ///  
        ///     Critical: Because it accesses _hwndTarget
        ///     TreatAsSafe: We don't pass it out; it is just used to convert to logical units 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private Size GetSizeFromHwnd() 
        {
            // Compute View's size and set
            NativeMethods.RECT rc = new NativeMethods.RECT(0, 0, 0, 0);
 
            if (_adjustSizingForNonClientArea == true)
            { 
                // get correct size for avalon Window (standalone and browser case) 
                GetSizeForWindowObject(ref rc);
            } 
            else
            {
                SafeNativeMethods.GetClientRect(new HandleRef(this,_hwndWrapper.Handle), ref rc);
            } 

            Point convertedPt = _hwndTarget.TransformFromDevice.Transform(new Point(rc.right - rc.left, rc.bottom - rc.top)); 
            return new Size(convertedPt.X, convertedPt.Y); 
        }
 
        /// 
        ///     Critical: This code can be used to spoof input
        /// 
        [SecurityCritical] 
        private IntPtr HwndTargetFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        { 
            IntPtr result = IntPtr.Zero ; 

            if (IsUsable) 
            {
                HwndTarget hwndTarget = _hwndTarget;
                if (hwndTarget != null)
                { 
                    result = hwndTarget.HandleMessage(msg, wParam, lParam);
                    if (result != IntPtr.Zero) 
                    { 
                        handled = true;
                    } 
                }

            }
 
            return result;
        } 
 
        /// 
        /// Critical:These hooks can all be used for input spoofing 
        /// 
        [SecurityCritical]
        private IntPtr LayoutFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        { 
            IntPtr result = IntPtr.Zero ;
 
            // We have to revalidate everything because the Access() call 
            // could have caused the CLR to enter a nested message pump,
            // during which almost anything could have happened that might 
            // invalidate our checks.
            UIElement rootUIElement=null;
            rootUIElement = _rootVisual.Value as UIElement;
            if (IsUsable && rootUIElement != null) 
            {
                switch (msg) 
                { 
                    // A window receives this message when the user chooses a command from
                    // the Window menu or when the user chooses the maximize button, minimize 
                    // button, restore button, or close button.
                    case NativeMethods.WM_SYSCOMMAND:
                        {
                            // The four low-order bits of the wParam parameter are used 
                            // internally by the system.
                            Int32 sysCommand = NativeMethods.IntPtrToInt32(wParam) & 0xFFF0; 
 
                            // Turn off SizeToContent if user chooses to maximize or resize.
                            if ((sysCommand == NativeMethods.SC_MAXIMIZE) || 
                                (sysCommand == NativeMethods.SC_SIZE))
                            {
                                DisableSizeToContent(rootUIElement, hwnd);
                            } 
                        }
                        break; 
 
                    // We get WM_SIZING. It means that user starts resizing the window.
                    // It is the first notification sent when user resizes (before WM_WINDOWPOSCHANGING) 
                    // and it's not sent if window is resized programmatically.
                    // SizeToContent is turned off after user resizes.
                    case NativeMethods.WM_SIZING:
                        DisableSizeToContent(rootUIElement, hwnd); 
                        break;
 
                    // The WM_WINDOWPOSCHANGING message is sent 
                    // 1. when the size, position, or place in the Z order is about to change as a result of a call to
                    //    the SetWindowPos function or other window-management functions. SizeToContent orverrides all in this case. 
                    // 2. when user resizes window. If it's user resize, we have turned SizeToContent off when we get WM_SIZING.
                    // It is sent before WM_SIZE.
                    // We can't use WM_GETMINMAXINFO, because if there is no window size change (we still need to make sure
                    // the client size not change), that notification wouldnt be sent. 
                    case NativeMethods.WM_WINDOWPOSCHANGING:
                        Process_WM_WINDOWPOSCHANGING(rootUIElement, hwnd, msg, wParam, lParam); 
                        break; 

                    // WM_SIZE message is sent after the size has changed. 
                    // lParam has the new width and height of client area.
                    // root element's size should be adjust based on the new width and height and SizeToContent's value.
                    case NativeMethods.WM_SIZE:
                        Process_WM_SIZE(rootUIElement, hwnd, msg, wParam, lParam); 
                        break;
                } 
            } 

            // Certain messages need to be processed while we are in the middle 
            // of construction - and thus an HwndTarget is not available.
            if(!handled && (_constructionParameters != null || IsUsable))
            {
                // Get the usesPerPixelOpacity from either the constructor parameters or the HwndTarget. 
                bool usesPerPixelOpacity = _constructionParameters != null ? ((HwndSourceParameters)_constructionParameters).UsesPerPixelOpacity : _hwndTarget.UsesPerPixelOpacity;
 
                switch(msg) 
                {
                    case NativeMethods.WM_NCCALCSIZE: 
                        {
                            // Windows that use per-pixel opacity don't get
                            // their frames drawn by the system.  Generally
                            // this is OK, as users of per-pixel alpha tend 
                            // to be doing customized UI anyways.  But we
                            // don't render correctly if we leave a non-client 
                            // area, so here we expand the client area to 
                            // cover any non-client area.
                            // 
                            if(usesPerPixelOpacity)
                            {
                                if(wParam == IntPtr.Zero)
                                { 
                                    // If wParam is FALSE, lParam points to a RECT
                                    // structure. On entry, the structure contains 
                                    // the proposed window rectangle for the 
                                    // window. On exit, the structure should
                                    // contain the screen coordinates of the 
                                    // corresponding window client area.
                                    //
                                    // Since all we want to do is make the client
                                    // rect the same as the window rect, we don't 
                                    // have to do anything.
                                    // 
                                    result = IntPtr.Zero; 
                                    handled = true;
                                } 
                                else
                                {
                                    // If wParam is TRUE, lParam points to an
                                    // NCCALCSIZE_PARAMS structure that contains 
                                    // information an application can use to
                                    // calculate the new size and position of 
                                    // the client rectangle. 
                                    //
                                    // When Windows sends the WM_NCCALCSIZE 
                                    // message, the NCCALCSIZE_PARAMS structure
                                    // is filled out like this:
                                    //
                                    // rgrc[0] = new window rectangle (in parent coordinates) 
                                    // rgrc[1] = old window rectangle (in parent coordinates)
                                    // rgrc[2] = old client rectangle (in parent coordinates) 
                                    // 
                                    // Notice that the client rectangle is given
                                    // in parent coordinates, not in client 
                                    // coordinates.
                                    //
                                    // When your window procedure returns, Windows
                                    // expects the NCCALCSIZE_PARAMS structure to 
                                    // be filled out like this:
                                    // 
                                    // rgrc[0] = new client rectangle (in parent coordinates) 
                                    //
                                    // Furthermore, if you return anything other 
                                    // than 0, Windows expects the remaining two
                                    // rectangles to be filled out like this:
                                    //
                                    // rgrc[1] = destination rectangle (in parent coordinates) 
                                    // rgrc[2] = source rectangle (in parent coordinates)
                                    // 
                                    // (If you return 0, then Windows assumes that 
                                    // the destination rectangle equals the new
                                    // client rectangle and the source rectangle 
                                    // equals the old client rectangle.)
                                    //
                                    // Since all we want to do is make the client
                                    // rect the same as the window rect, we don't 
                                    // have to do anything.
                                    // 
                                    result = IntPtr.Zero; 
                                    handled = true;
                                } 
                            }
                        }
                        break;
                } 
            }
 
            return result; 
        }
 
        /// 
        /// Critical: Because it uses _hwndTarget
        /// 
        [SecurityCritical] 
        private void Process_WM_WINDOWPOSCHANGING(UIElement rootUIElement, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
        { 
            // Only if SizeToContent overrides Win32 sizing change calls. 
            // If it's coming from OnResize (_myOwnUpdate != true), it means we are adjusting
            // to the right size; don't need to do anything here. 
            if ((_myOwnUpdate != true) && (SizeToContent != SizeToContent.Manual))
            {
                Size sz = rootUIElement.RenderSize;
                Point pt = _hwndTarget.TransformToDevice.Transform(new Point(sz.Width, sz.Height)); 

                RoundDeviceSize(ref pt); 
                NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, (int)pt.X, (int)pt.Y); 

                // get the outside size of the window only if LM has the client area 
                // as its size.  LM has the client are when it is not the app model
                // window case thus we calculate the outside size here.
                //
                // For windows with UsesPerPixelOpacity, we force the client to 
                // fill the window, so we don't need to add in any frame space.
                // 
                if (_adjustSizingForNonClientArea == false && !UsesPerPixelOpacity) 
                {
                    // Get the current style and calculate the size to be with the new style. 
                    // If WM_WINDOWPOSCHANGING is sent because of style changes, WM_STYLECHANGED is sent
                    // before this. The style bits we get here are updated ones, but haven't been applied
                    // to Window yet. For example, when the window is changing to borderless, without updating the window size,
                    // the window size will remain the same but the client area will be bigger. So when SizeToContent is on, we calculate 
                    // the window size to be with the new style using AdustWindowRectEx and adjust it to make sure client area is not affected.
                    int style = NativeMethods.IntPtrToInt32((IntPtr)SafeNativeMethods.GetWindowStyle(new HandleRef(this,_hwndWrapper.Handle), false)); 
                    int styleEx = NativeMethods.IntPtrToInt32((IntPtr)SafeNativeMethods.GetWindowStyle(new HandleRef(this,_hwndWrapper.Handle), true)); 

                    SafeNativeMethods.AdjustWindowRectEx(ref rect, style, false, styleEx); 
                }

                int newCX = rect.right - rect.left;
                int newCY = rect.bottom - rect.top; 

                // Get WINDOWPOS structure data from lParam; it contains information about the window's 
                // new size and position. 
                NativeMethods.WINDOWPOS windowPos = (NativeMethods.WINDOWPOS)UnsafeNativeMethods.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS));
 
                bool sizeChanged = false;

                // If SWP_NOSIZE is set to ignore cx, cy. It could be a style or position change.
                if ((windowPos.flags & NativeMethods.SWP_NOSIZE) == NativeMethods.SWP_NOSIZE) 
                {
                    NativeMethods.RECT windowRect = new NativeMethods.RECT(0, 0, 0, 0); 
 
                    // Get the current Window rect
                    SafeNativeMethods.GetWindowRect(new HandleRef(this, _hwndWrapper.Handle), ref windowRect); 

                    // If there is no size change with the new style we don't need to do anything.
                    if ((newCX != (windowRect.right - windowRect.left)) ||
                        (newCY != (windowRect.bottom - windowRect.top))) 
                    {
                        // Otherwise unmark the flag to make our changes effective. 
                        windowPos.flags &= ~NativeMethods.SWP_NOSIZE; 

                        // When SWP_NOSIZE is on, the size info in cx and cy is bogus. They are ignored. 
                        // When we turn it off, we need to provide valid value for both of them.
                        windowPos.cx = newCX;
                        windowPos.cy = newCY;
                        sizeChanged = true; 
                    }
                } 
                else 
                {
                    // We have excluded SizeToContent == SizeToContent.Manual before entering this. 
                    bool sizeToWidth = (SizeToContent == SizeToContent.Height) ? false : true;
                    bool sizeToHeight = (SizeToContent == SizeToContent.Width) ? false : true;

                    // Update WindowPos with the size we want. 
                    if ((sizeToWidth) && (windowPos.cx != newCX))
                    { 
                        windowPos.cx = newCX; 
                        sizeChanged = true;
                    } 

                    if ((sizeToHeight) && (windowPos.cy != newCY))
                    {
                        windowPos.cy = newCY; 
                        sizeChanged = true;
                    } 
                } 

                // Marshal the structure back only when changed 
                if (sizeChanged)
                {
                    Marshal.StructureToPtr(windowPos, lParam, true);
                } 
            }
        } 
 
        /// 
        /// Critical: Because it uses _hwndTarget 
        /// 
        [SecurityCritical]
        private void Process_WM_SIZE(UIElement rootUIElement, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
        { 
            int x = NativeMethods.SignedLOWORD(lParam);
            int y = NativeMethods.SignedHIWORD(lParam); 
            Point pt = new Point(x, y); 
            bool etwEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal);
            int  ctxHashCode = 0; 

            // 1. If it's coming from Layout (_myOwnUpdate), it means we are adjusting
            // to the right size; don't need to do anything here.
            // 2. If SizeToContent is set to WidthAndHeight, then we maintain the current hwnd size 
            // in WM_WINDOWPOSCHANGING, so we don't need to re-layout here.  If SizeToContent
            // is set to Width or Height and developer calls SetWindowPos to set a new 
            // Width/Height, we need to do a layout. 
            // 3. We also don't need to do anything if it's minimized.
 
            // Keeps the status of whether the Window is in Minimized state or not.
            _isWindowInMinimizeState = (NativeMethods.IntPtrToInt32(wParam) == NativeMethods.SIZE_MINIMIZED) ? true : false;

            if ((!_myOwnUpdate) && (_sizeToContent != SizeToContent.WidthAndHeight) && !_isWindowInMinimizeState) 
            {
                Point relevantPt = new Point(pt.X, pt.Y); 
 
                // WM_SIZE has the client size of the window.
                // for appmodel window case, get the outside size of the hwnd. 
                if (_adjustSizingForNonClientArea == true)
                {
                    NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, (int)pt.X, (int)pt.Y);
                    GetSizeForWindowObject(ref rect); 
                    relevantPt.X = rect.right - rect.left;
                    relevantPt.Y = rect.bottom - rect.top; 
                } 

                // The lParam/wParam size and the GetSizeForWindowObject size are 
                // both in device co-ods, thus we convert to Measure co-ods here.
                relevantPt = _hwndTarget.TransformFromDevice.Transform(relevantPt);

                Size sz = new Size( 
                    (_sizeToContent == SizeToContent.Width ? double.PositiveInfinity : relevantPt.X),
                    (_sizeToContent == SizeToContent.Height ? double.PositiveInfinity : relevantPt.Y)); 
 
                // NOTE: [....] -- 6/03/04
                // 962884 Avalon content does not resize when the favorites 
                // (or other side pane) is closed
                //
                // The issue is that when the browser shows favorites window, avalon
                // window is resized and we get WM_SIZE.  Here, we pass the IE window's 
                // size to Measure so that Computed[Width/Height] gets the correct
                // IE window dimensions.  Since, IE window's size may not change, the 
                // call to Measure is optimized out and no layout happens.  Invalidating 
                // layout here ensures that we do layout.
                // This can happen only in the Window case 
                if (_adjustSizingForNonClientArea == true)
                {
                    rootUIElement.InvalidateMeasure();
                } 

                if (etwEnabled) 
                { 
                    ctxHashCode = this.Dispatcher.GetHashCode();
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
                }
 
                rootUIElement.Measure(sz);
 
                if (_sizeToContent == SizeToContent.Width) sz = new Size(rootUIElement.DesiredSize.Width, relevantPt.Y); 
                else if (_sizeToContent == SizeToContent.Height) sz = new Size(relevantPt.X, rootUIElement.DesiredSize.Height);
                else sz = new Size(relevantPt.X, relevantPt.Y); 

                if (etwEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent); 

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 
                } 

                rootUIElement.Arrange(new Rect(new Point(), sz)); 

                if (etwEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent); 

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent); 
                } 
                rootUIElement.UpdateLayout(); //finalizes layout
 
            }
        }

        ///  
        /// Critical: Because it uses _hwndTarget
        ///  
        [SecurityCritical] 
        private void DisableSizeToContent(UIElement rootUIElement, IntPtr hwnd)
        { 
            if (_sizeToContent != SizeToContent.Manual)
            {
                _sizeToContent = SizeToContent.Manual;
 
                // [....] - 10/27/2005
                // 1348020 Window expereience layout issue when SizeToContent is being turned 
                // off by user interaction 
                // This bug was caused b/c we were giving rootUIElement.DesiredSize as input
                // to Measure/Arrange below.  That is incorrect since rootUIElement.DesiredSize may not 
                // cover the entire hwnd client area.

                // GetSizeFromHwnd returns either the outside size or the client size of the hwnd based on
                // _adjustSizeingForNonClientArea flag in logical units. 
                Size sizeLogicalUnits = GetSizeFromHwnd();
                rootUIElement.Measure(sizeLogicalUnits); 
                rootUIElement.Arrange(new Rect(new Point(), sizeLogicalUnits)); 

                rootUIElement.UpdateLayout(); //finalizes layout 


                if (SizeToContentChanged != null)
                { 
                    SizeToContentChanged(this, EventArgs.Empty);
                } 
            } 
        }
 
        // This method makes sure that we get the size from the correct
        // hwnd for the browser case.
        /// 
        /// Critical - calls critical methods (HwndSourceHelper.GetHandle and GetAncestor) 
        /// TreatAsSafe - it's ok to return size of window. it doesn't return info gotten through critical calls.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void GetSizeForWindowObject(ref NativeMethods.RECT rc)
        { 
            IntPtr hwndRoot = UnsafeNativeMethods.GetAncestor(new HandleRef(this, CriticalHandle), NativeMethods.GA_ROOT);
            SafeNativeMethods.GetWindowRect(new HandleRef(this, hwndRoot), ref rc);
        }
 
        /// 
        ///     Critical: This is a hook that gets called back with information about messages related to input 
        ///     Calling this from outside or causing this to be invoked could yield risky situations 
        /// 
        [SecurityCritical] 
        private IntPtr InputFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            IntPtr result = IntPtr.Zero ;
 
            // NOTE ([....]): invoke _stylus.FilterMessage before _mouse.FilterMessage
            // to give _stylus a chance to eat mouse message generated by stylus 
            if (!_isDisposed && _stylus != null && !handled) 
            {
                result = _stylus.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled); 
            }

            if (!_isDisposed && _mouse != null && !handled)
            { 
                result = _mouse.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled);
            } 
 
            if (!_isDisposed && _keyboard != null && !handled)
            { 
                result = _keyboard.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled);
            }

            if (!_isDisposed && _appCommand != null && !handled) 
            {
                result = _appCommand.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled); 
            } 

            return result; 
        }

        /// 
        ///    Called from HwndWrapper on all window messages. 
        /// 
        // assumes Context.Access() is held. 
        private IntPtr PublicHooksFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
        {
            // The default result for messages we handle is 0. 
            IntPtr result = IntPtr.Zero ;

            // Call all of the public hooks
            // We do this even if we are disposed because otherwise the hooks 
            // would never see the WM_DESTROY etc. message.
            if (_hooks != null) 
            { 
                for (int i = 0, nCount = _hooks.Count; i < nCount; i++)
                { 
                    result = ((HwndSourceHook)_hooks[i])(hwnd, msg, wParam, lParam, ref handled);
                    if(handled)
                    {
                        break; 
                    }
                } 
            } 
            if (NativeMethods.WM_NCDESTROY == msg)
            { 
                // We delivered the message to the hooks and the message
                // is WM_NCDESTROY, so our commitments should be finished
                // we can do final teardown. (like disposing the _hooks)
                OnNoMoreWindowMessages(); 
            }
 
            return result; 
        }
 
#region IKeyboardInputSink
        private class MSGDATA
        {
            public MSG msg; 
            public bool handled;
        } 
 
        /// 
        /// HwndSource keyboard input is sent through this delegate to check for 
        /// Child Hwnd interop requirments.  If there are no child hwnds or focus
        /// is on this non-child hwnd then normal Avalon processing is done.
        /// 
        /// 
        /// Critical - This can be used to spoof input
        ///  
        [SecurityCritical] 
        private void OnPreprocessMessageThunk(ref MSG msg, ref bool handled)
        { 
//             VerifyAccess();

            if (handled)
            { 
                return;
            } 
 
            // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
            if(msg.message ==  _msgEnableCharMessages) 
            {
                // This is our cue to go back to accepting character messages
                _eatCharMessages = false;
            } 

            // We only do these message. 
            switch (msg.message) 
            {
            case NativeMethods.WM_KEYUP: 
            case NativeMethods.WM_KEYDOWN:
            case NativeMethods.WM_SYSKEYUP:
            case NativeMethods.WM_SYSKEYDOWN:
            case NativeMethods.WM_CHAR: 
            case NativeMethods.WM_SYSCHAR:
            case NativeMethods.WM_DEADCHAR: 
            case NativeMethods.WM_SYSDEADCHAR: 
                MSGDATA msgdata = new MSGDATA();
                msgdata.msg = msg; 
                msgdata.handled = handled;

                // Do this under the exception filter/handlers of the
                // dispatcher for this thread. 
                //
                // NOTE: we lose the "perf optimization" of passing everything 
                // around by-ref since we have to call through a delegate. 
                object result = Dispatcher.CurrentDispatcher.Invoke(
                    DispatcherPriority.Send, 
                    new DispatcherOperationCallback(OnPreprocessMessage),
                    msgdata);

                if (result != null) 
                {
                    handled = (bool)result; 
                } 

                // the semantics dictate that the callers could change this data. 
                msg = msgdata.msg;
                break;
            }
        } 

 
        ///  
        /// Critical - Can be used to spoof input
        ///  
        [SecurityCritical]
        private object OnPreprocessMessage(object param)
        {
            MSGDATA msgdata = (MSGDATA) param; 

            // At the top level check if someone below us has Focus. 
            // Mnemonics are broadcast to all branches of the window tree; even 
            // those that don't have focus.  BUT! at least someone under this
            // TopLevel window must have focus. 
            if (!((IKeyboardInputSink)this).HasFocusWithin())
            {
                return msgdata.handled;
            } 

            ModifierKeys modifierKeys = HwndKeyboardInputProvider.GetSystemModifierKeys(); 
 
            // Interop with the Interop layer
            // 
            switch (msgdata.msg.message)
            {
            case NativeMethods.WM_SYSKEYDOWN:
            case NativeMethods.WM_KEYDOWN: 
                // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
                // In case a nested message pump is used before we return 
                // from processing this message, we disable character 
                // messages.
                _eatCharMessages = true; 

                // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
                _eatCharMessages = msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys);
                if(_eatCharMessages) 
                {
                    UnsafeNativeMethods.PostMessage(new HandleRef(this, CriticalHandle), _msgEnableCharMessages, IntPtr.Zero, IntPtr.Zero); 
 
                }
                break; 

            case NativeMethods.WM_SYSKEYUP:
            case NativeMethods.WM_KEYUP:
                msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys); 
                break;
 
            case NativeMethods.WM_CHAR: 
            case NativeMethods.WM_SYSCHAR:
            case NativeMethods.WM_DEADCHAR: 
            case NativeMethods.WM_SYSDEADCHAR:
                // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
                if(!_eatCharMessages)
                { 
                    msgdata.handled = ((IKeyboardInputSink)this).TranslateChar(ref msgdata.msg, modifierKeys);
 
                    if (!msgdata.handled) 
                    {
                        msgdata.handled = ((IKeyboardInputSink)this).OnMnemonic(ref msgdata.msg, modifierKeys); 
                    }

                    if (!msgdata.handled)
                    { 
                        _keyboard.Value.ProcessTextInputAction(msgdata.msg.hwnd, msgdata.msg.message,
                                                               msgdata.msg.wParam, msgdata.msg.lParam, ref msgdata.handled); 
                    } 
                }
                break; 
            }
            return msgdata.handled;
        }
 
        /// 
        ///     Registers a child KeyboardInputSink with this sink.  A site 
        ///     is returned. 
        /// 
        /// 
        /// This API requires unrestricted UI Window permission.
        ///
        /// 
        ///     Critical: This API can be used for input spoofing 
        ///     PublicOK: This method has a demand on it.
        ///  
        [SecurityCritical, UIPermissionAttribute(SecurityAction.Demand, Unrestricted=true)] 
        IKeyboardInputSite IKeyboardInputSink.RegisterKeyboardInputSink(IKeyboardInputSink sink)
        { 
            CheckDisposed(true);

            if (sink == null)
            { 
                throw new ArgumentNullException("sink");
            } 
 
            if (sink.KeyboardInputSite != null)
            { 
                throw new ArgumentException(SR.Get(SRID.KeyboardSinkAlreadyOwned));
            }

            HwndSourceKeyboardInputSite site = new HwndSourceKeyboardInputSite(this, sink); 

            if (_keyboardInputSinkChildren == null) 
                _keyboardInputSinkChildren = new List(); 
            _keyboardInputSinkChildren.Add(site);
 
            return site;
        }

        ///  
        ///     Gives the component a chance to process keyboard input.
        ///     Return value is true if handled, false if not.  Components 
        ///     will generally call a child component's TranslateAccelerator 
        ///     if they can't handle the input themselves.  The message must
        ///     either be WM_KEYDOWN or WM_SYSKEYDOWN.  It is illegal to 
        ///     modify the MSG structure, it's passed by reference only as
        ///     a performance optimization.
        /// 
        /// 
        /// This API is not available in Internet Zone.
        /// 
        ///  
        ///     Critical: This API can be used for input spoofing
        ///     TreatAsSafe: This method has a demand on it. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers)
        { 
            SecurityHelper.DemandUnmanagedCode();
//             VerifyAccess(); 
 
            return CriticalTranslateAccelerator(ref msg, modifiers);
        } 

        /// 
        ///     Set focus to the first or last tab stop (according to the
        ///     TraversalRequest).  If it can't, because it has no tab stops, 
        ///     the return value is false.
        ///  
        bool IKeyboardInputSink.TabInto(TraversalRequest request) 
        {
            bool traversed = false; 

            if(request == null)
            {
                throw new ArgumentNullException("request"); 
            }
 
            UIElement root =_rootVisual.Value as UIElement; 
            if(root != null)
            { 
                // [....]:
                // request.Mode == FocusNavigationDirection.First will navigate to the fist tabstop including root
                // request.Mode == FocusNavigationDirection.Last will navigate to the last tabstop including root
                traversed = root.MoveFocus(request); 
            }
 
            return traversed; 
        }
 
        /// 
        ///     The property should start with a null value.  The component's
        ///     container will set this property to a non-null value before
        ///     any other methods are called.  It may be set multiple times, 
        ///     and should be set to null before disposal.
        ///  
        /// 
        /// Setting KeyboardInputSite is not available in Internet Zone.
        /// 
        /// 
        ///     Critical: This API can be used for input spoofing
        ///     PublicOK: This method has a demand on it.
        ///  
        IKeyboardInputSite IKeyboardInputSink.KeyboardInputSite
        { 
            [SecurityCritical] 
            get
            { 
                SecurityHelper.DemandUnmanagedCode();
                return _keyboardInputSite;
            }
 
            [SecurityCritical]
            set 
            { 
                SecurityHelper.DemandUnmanagedCode();
 
                _keyboardInputSite = value;
            }
        }
 
        /// 
        ///     This method is called whenever one of the component's 
        ///     mnemonics is invoked.  The message must either be WM_KEYDOWN 
        ///     or WM_SYSKEYDOWN.  It's illegal to modify the MSG structrure,
        ///     it's passed by reference only as a performance optimization. 
        ///     If this component contains child components, the container
        ///     OnMnemonic will need to call the child's OnMnemonic method.
        /// 
        ///  
        ///     Critical: This API can be used for input spoofing
        ///     TreatAsSafe: This method has a demand on it. 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        bool IKeyboardInputSink.OnMnemonic(ref MSG msg, ModifierKeys modifiers) 
        {
//             VerifyAccess();
            SecurityHelper.DemandUnmanagedCode();
            switch(msg.message) 
            {
                case NativeMethods.WM_SYSCHAR: 
                case NativeMethods.WM_SYSDEADCHAR: 
                    string text = new string((char)msg.wParam, 1);
                    if ((text != null) && (text.Length > 0)) 
                    {
                        if (AccessKeyManager.IsKeyRegistered(this, text))
                        {
                            AccessKeyManager.ProcessKey(this, text, false); 

                            // 
                            return true; 
                        }
                    } 
                    // these are OK
                    break;

                case NativeMethods.WM_CHAR: 
                case NativeMethods.WM_DEADCHAR:
                    // these are OK 
                    break; 

                default: 
                    throw new ArgumentException(SR.Get(SRID.OnlyAcceptsKeyMessages));
            }

            // We record the last message that was processed by us. 
            // This is also checked in WndProc processing to prevent double processing.
            _lastKeyboardMessage = msg; 
 
            // The Avalon bubble will take care of access key processing for this HWND
            // So now we just call the children. 
            if (null == _keyboardInputSinkChildren)
                return false;

            foreach ( HwndSourceKeyboardInputSite childSite in _keyboardInputSinkChildren ) 
            {
                if (((IKeyboardInputSite)childSite).Sink.OnMnemonic(ref msg, modifiers)) 
                    return true; 
            }
            return false; 
        }

        /// 
        ///     Gives the component a chance to process keyboard input messages 
        ///     WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR before calling OnMnemonic.
        ///     Will return true if "handled" meaning don't pass it to OnMnemonic. 
        ///     The message must be WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR. 
        ///     It is illegal to modify the MSG structure, it's passed by reference
        ///     only as a performance optimization. 
        /// 
        /// 
        ///     Critical: This API can be used for input spoofing
        ///     TreatAsSafe: This method has a demand on it. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        bool IKeyboardInputSink.TranslateChar(ref MSG msg, ModifierKeys modifiers) 
        {
            SecurityHelper.DemandUnmanagedCode(); 
            if(HasFocus)
                return false;

            IKeyboardInputSink focusSink = this.ChildSinkWithFocus; 
            if(null != focusSink)
            { 
                return focusSink.TranslateChar(ref msg, modifiers); 
            }
            return false; 
        }

        /// 
        /// 
        /// 
        bool IKeyboardInputSink.HasFocusWithin() 
        { 
            if(HasFocus)
            { 
                return true;
            }
            else
            { 
                if (null == _keyboardInputSinkChildren)
                    return false; 
 
                foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren)
                { 
                    if (((IKeyboardInputSite)site).Sink.HasFocusWithin())
                    {
                        return true;
                    } 
                }
                return false; 
            } 
        }
 
        /// 
        ///   The method is not part of the interface (IKeyboardInputSink).
        /// 
        /// The Site that containes the sink to unregister 
        /// 
        ///     Critical - calls critical methods. 
        ///  
        [ SecurityCritical ]
        internal void CriticalUnregisterKeyboardInputSink(HwndSourceKeyboardInputSite site) 
        {
            if(_isDisposed)
                return;
 
            if (null != _keyboardInputSinkChildren)
            { 
                if (!_keyboardInputSinkChildren.Remove(site)) 
                {
                    throw new InvalidOperationException(SR.Get(SRID.KeyboardSinkNotAChild)); 
                }
            }
        }
 
        IKeyboardInputSink ChildSinkWithFocus
        { 
            get 
            {
                IKeyboardInputSink ikis=null; 

                if(null == _keyboardInputSinkChildren)
                    return null;
 
                foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren)
                { 
                    IKeyboardInputSite isite = (IKeyboardInputSite)site; 

                    if (isite.Sink.HasFocusWithin()) 
                    {
                        ikis = isite.Sink;
                        break;
                    } 
                }
                // This private property should only be called correctly. 
                Debug.Assert(null!=ikis, "ChildSinkWithFocus called when none had focus"); 
                return ikis;
            } 
        }

        /// 
        ///     Critical: This API could be vulnerable to input spoofing. 
        /// 
        [SecurityCritical, FriendAccessAllowed] 
        internal bool CriticalTranslateAccelerator(ref MSG msg, ModifierKeys modifiers) 
        {
            switch (msg.message) 
            {
                case NativeMethods.WM_KEYUP:
                case NativeMethods.WM_KEYDOWN:
                case NativeMethods.WM_SYSKEYUP: 
                case NativeMethods.WM_SYSKEYDOWN:
                    // these are OK 
                    break; 

                default: 
                    throw new ArgumentException(SR.Get(SRID.OnlyAcceptsKeyMessages));
            }

            if (_keyboard == null) 
                return false;
 
            bool handled = false; 

            // TranslateAccelerator is called recursively on child Hwnds (Source & Host) 
            // If this is the first Avalon TranslateAccelerator processing then we send the
            // key to be processed to the standard Avalon Input Filters and stuff.
            if (PerThreadData.TranslateAcceleratorCallDepth == 0)
            { 
                // We record the last message that was processed by us.
                // This is also checked in WndProc processing to prevent double processing. 
                // TranslateAcclerator is called from the pump before DispatchMessage 
                // and the WndProc is called from DispatchMessage.   We have processing
                // in both places.  If we run the pump we process keyboard message here. 
                // If we don't own the pump we process them in HwndKeyboardInputProvider.WndProc.
                _lastKeyboardMessage = msg;

                //  NORMAL AVALON KEYBOARD INPUT CASE 
                // If this is the top most Avalon window (it might be a child Hwnd
                // but no Avalon windows above it).  And focus is on this window then 
                // do the Normal Avalon Keyboard input Processing. 
                if (HasFocus)
                { 
                    _keyboard.Value.ProcessKeyAction(ref msg, ref handled);
                }
                // ELSE the focus is in but not on this HwndSource.
                // Do the once only message input filters etc and Tunnel/Bubble down 
                // to the element that contains the child window with focus.
                // The Child HwndHost object will hook OnPreviewKeyDown() etc 
                // to make the transition to its TranslateAccelerator() between the 
                // tunnel and the bubble.
                else 
                {
                    IKeyboardInputSink focusSink = ChildSinkWithFocus;
                    IInputElement focusElement = (IInputElement)focusSink;
 
                    try {
                        PerThreadData.TranslateAcceleratorCallDepth += 1; 
                        Keyboard.PrimaryDevice.ForceTarget = focusElement; 
                       _keyboard.Value.ProcessKeyAction(ref msg, ref handled);
                    } 
                    finally
                    {
                        Keyboard.PrimaryDevice.ForceTarget = null;
                        PerThreadData.TranslateAcceleratorCallDepth -= 1; 
                    }
                } 
 
            }
            // ELSE we have seen this MSG before, we are HwndSource decendant of an 
            // HwndSource (that ancestor presumably did the processing above).
            // Here we raise the tunnel/bubble events without the once only keyboard
            // input filtering.
            else 
            {
                int virtualKey = HwndKeyboardInputProvider.GetVirtualKey(msg.wParam, msg.lParam); 
                int scanCode = HwndKeyboardInputProvider.GetScanCode(msg.wParam, msg.lParam); 
                bool isExtendedKey = HwndKeyboardInputProvider.IsExtendedKey(msg.lParam);
                Key key = KeyInterop.KeyFromVirtualKey(virtualKey); 

                RoutedEvent keyPreviewEvent=null;
                RoutedEvent keyEvent=null;
                switch (msg.message) 
                {
                case NativeMethods.WM_KEYUP: 
                case NativeMethods.WM_SYSKEYUP: 
                    keyPreviewEvent = Keyboard.PreviewKeyUpEvent;
                    keyEvent = Keyboard.KeyUpEvent; 
                    break;
                case NativeMethods.WM_KEYDOWN:
                case NativeMethods.WM_SYSKEYDOWN:
                    keyPreviewEvent = Keyboard.PreviewKeyDownEvent; 
                    keyEvent = Keyboard.KeyDownEvent;
                    break; 
                } 

                IKeyboardInputSink focusSink = HasFocus ? null : ChildSinkWithFocus; 
                IInputElement focusElement = focusSink as IInputElement;

                // focusElement may be null, in which case Target is just "focus"
                try { 
                    Keyboard.PrimaryDevice.ForceTarget = focusElement;
                    focusElement = Keyboard.PrimaryDevice.Target; 
 
                    KeyEventArgs tunnelArgs = new KeyEventArgs(Keyboard.PrimaryDevice, this, msg.time, key);
                    tunnelArgs.ScanCode = scanCode; 
                    tunnelArgs.IsExtendedKey = isExtendedKey;
                    tunnelArgs.RoutedEvent = keyPreviewEvent;
                    focusElement.RaiseEvent(tunnelArgs);
 
                    handled = tunnelArgs.Handled;
                    if (!handled) 
                    { 
                        KeyEventArgs bubbleArgs = new KeyEventArgs(Keyboard.PrimaryDevice, this, msg.time, key);
                        bubbleArgs.ScanCode = scanCode; 
                        bubbleArgs.IsExtendedKey = isExtendedKey;
                        bubbleArgs.RoutedEvent=keyEvent;
                        focusElement.RaiseEvent(bubbleArgs);
 
                        handled = bubbleArgs.Handled;
                        if (!handled) 
                        { 
                            // Raise the TranslateAccelerator event on the
                            // InputManager to allow keyboard navigation to 
                            // happen on a descendent HwndSource
                            InputManager.UnsecureCurrent.RaiseTranslateAccelerator(bubbleArgs);
                            handled = bubbleArgs.Handled;
                        } 
                    }
                } 
                finally 
                {
                    Keyboard.PrimaryDevice.ForceTarget = null; 
                }
            }

            return handled; 
        }
 
#endregion IKeyboardInputSink 

 
        internal bool IsRepeatedKeyboardMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
        {
            if (msg != _lastKeyboardMessage.message)
                return false; 
            if (hwnd != _lastKeyboardMessage.hwnd)
                return false; 
            if (wParam != _lastKeyboardMessage.wParam) 
                return false;
            if (lParam != _lastKeyboardMessage.lParam) 
                return false;
            return true;
        }
 
        /// 
        ///    This event handler is called from HwndWrapper when it is Disposing. 
        ///  
        // This could happen if someone calls his Dispose before (or instead
        // of) our dispose.  Or, more likely, the real window was killed by 
        // something like the user clicking the close box.
        private void OnHwndDisposed(object sender, EventArgs args)
        {
            // This method is called from the HwndWrapper.Dispose(). 
            // So make sure we don't call HwndWrapper.Dispose().
            _inRealHwndDispose = true; 
            Dispose(); 
        }
 
        /// 
        ///    Called after the last window message is processed.
        /// 
 
        // HwndSource is required to continue certain operations while,
        // and even after, Dispose runs.  HwndSource is resposible for 
        // calling WndProcHooks with every message the window sees. 
        // Including: WM_CLOSE, WM_DESTROY, WM_NCDESTROY.  The doc says
        // WM_NCDESTROY is the very last message, so we can release the 
        // Hooks after that.
        // This assumes the Context.Access() is held.
        private void OnNoMoreWindowMessages()
        { 
            _hooks.Clear();
            _hooks = null; 
        } 

        private void OnShutdownFinished(object sender, EventArgs args) 
        {
            // Note: We are already in the context being disposed.
            Dispose();
        } 

        // 
        // NOTE: shutdown order is very important.  Review any changes 
        // carefully.
        // 
        /// 
        ///     Critical: This accesses the various sites and providers
        ///     Safe: Disposing the object is a safe operation.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void Dispose(bool disposing) 
        { 
            if(disposing)
            { 
                // Make sure all access is synchronized.
//                 this.VerifyAccess();

                if (!_isDisposing) 
                {
                    // _isDisposing is a guard against re-entery into this 
                    // routine.  We fire Dispose and SourceChanged (RootVisual 
                    // change) events which could cause re-entery.
                    _isDisposing = true; 

                    // Notify listeners that we are being disposed.  We do this
                    // before we dispose our internal stuff, in case the event
                    // listener needs to access something. 
                    if(Disposed != null)
                    { 
                        try 
                        {
                            Disposed(this, EventArgs.Empty); 
                        }
#pragma warning disable 56500
                        // We can't tolerate an exception thrown by third-party code to
                        // abort our Dispose half-way through.  So we just eat it. 
                        catch
                        { 
                        } 
#pragma warning restore 56500
                        Disposed = null; 
                    }

                    // Remove any listeners of the ContentRendered event
                    ClearContentRenderedListeners(); 

                    // Clear the root visual.  This will raise a SourceChanged 
                    // event to registered listeners. 
                    RootVisualInternal = null;
                    RemoveSource(); 

                    // Unregister ourselves if we are a registered KeyboardInputSink.
                    if(_keyboardInputSite != null)
                    { 
                        _keyboardInputSite.Unregister();
                        _keyboardInputSite = null; 
                    } 
                    _keyboardInputSinkChildren = null;
 
                    // Dispose the HwndStylusInputProvider BEFORE we destroy the HWND.
                    // This us because the stylus provider has an async channel and
                    // they don't want to process data after the HWND is destroyed.
                    if (_stylus != null) 
                    {
                        _stylus.Value.Dispose(); 
                        _stylus = null; 
                    }
 
                    // Our general shut-down principle is to destroy the window
                    // and let the individual HwndXXX components respons to WM_DESTROY.
                    //
                    // (see comment above about disposing the HwndStylusInputProvider) 
                    //
                    { 
                        if (_hwndTarget != null) 
                        {
                            _hwndTarget.Dispose(); 
                            _hwndTarget = null;
                        }

                        if (_hwndWrapper != null) 
                        {
                            // Revoke the drop target. 
                            if (_hwndWrapper.Handle != IntPtr.Zero && _registeredDropTargetCount > 0) 
                            {
                                // This call is safe since DragDrop.RevokeDropTarget is checking the unmanged 
                                // code permission.
                                DragDrop.RevokeDropTarget(_hwndWrapper.Handle);
                                _registeredDropTargetCount--;
                            } 

                            // Remove our HwndWrapper.Dispose() hander. 
                            _hwndWrapper.Disposed -= new EventHandler(OnHwndDisposed); 

                            if (!_inRealHwndDispose) 
                                _hwndWrapper.Dispose();

                            // Don't null out _hwndWrapper after the Dispose().
                            // Dispose() will start destroying the Window but we 
                            // still need to talk to it during that process while
                            // the WM_ msgs arrive. 
                        } 
                    }
 
                    if(_mouse != null)
                    {
                        _mouse.Value.Dispose();
                        _mouse = null; 
                    }
 
                    if(_keyboard != null) 
                    {
                        _keyboard.Value.Dispose(); 
                        _keyboard = null;
                    }

                    if (_appCommand != null) 
                    {
                        _appCommand.Value.Dispose(); 
                        _appCommand = null; 
                    }
 
                    if(null != _weakShutdownHandler)
                    {
                        _weakShutdownHandler.Dispose();
                        _weakShutdownHandler = null; 
                    }
 
                    if(null != _weakPreprocessMessageHandler) 
                    {
                        _weakPreprocessMessageHandler.Dispose(); 
                        _weakPreprocessMessageHandler = null;
                    }

                    // We wait to set the "_isDisposed" flag until after the 
                    // Disposed, SourceChange (RootVisual=null), etc. events
                    // have fired.  We want to remain functional should their 
                    // handlers call methods on us. 
                    //
                    // Note: as the HwndWrapper shuts down, the final few messages 
                    // will continue to pass through our WndProc hook.
                    _isDisposed = true;
                }
            } 
        }
 
        private void CheckDisposed(bool verifyAccess) 
        {
            if(verifyAccess) 
            {
//                 this.VerifyAccess();
            }
 
            if(_isDisposed)
            { 
                throw new ObjectDisposedException(null, SR.Get(SRID.HwndSourceDisposed)); 
            }
        } 

        /// 
        ///     Critical: This code accesses hwndtarget
        ///     TreatAsSafe: Information is ok to expose 
        /// 
        private bool IsUsable 
        { 
            [SecurityCritical,SecurityTreatAsSafe]
            get 
            {
                return _isDisposed == false &&
                       _hwndTarget != null &&
                       _hwndTarget.IsDisposed == false; 
            }
        } 
 
        /// 
        ///     Critical - calls a method with an elevation ( GetFocus ) 
        ///     TreatAsSafe - determining whether you have focus within the window is considered safe.
        ///                   Worst case you can know whether keyboard/keypress events will go to the current window.
        /// 
        private bool HasFocus 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get 
            {
                return UnsafeNativeMethods.GetFocus() == CriticalHandle; 
            }
        }

        private static bool IsValidSizeToContent(SizeToContent value) 
        {
            return value == SizeToContent.Manual || 
                   value == SizeToContent.Width  || 
                   value == SizeToContent.Height ||
                   value == SizeToContent.WidthAndHeight; 
        }

        class ThreadDataBlob
        { 
            public int TranslateAcceleratorCallDepth;
        } 
 
        private static ThreadDataBlob PerThreadData
        { 
            get
            {
                ThreadDataBlob data;
                object obj = Thread.GetData(_threadSlot); 
                if(null == obj)
                { 
                    data = new ThreadDataBlob(); 
                    Thread.SetData(_threadSlot, data);
                } 
                else
                {
                    data = (ThreadDataBlob) obj;
                } 
                return data;
            } 
        } 

#region WeakEventHandlers 

        private class WeakEventDispatcherShutdown: WeakReference
        {
            public WeakEventDispatcherShutdown(HwndSource source, Dispatcher that): base(source) 
            {
                _that = that; 
                _that.ShutdownFinished += new EventHandler(this.OnShutdownFinished); 
            }
 
            public void OnShutdownFinished(object sender, EventArgs e)
            {
                HwndSource source = this.Target as HwndSource;
                if(null != source) 
                {
                    source.OnShutdownFinished(sender, e); 
                } 
                else
                { 
                    Dispose();
                }
            }
 
            public void Dispose()
            { 
                if(null != _that) 
                {
                    _that.ShutdownFinished-= new EventHandler(this.OnShutdownFinished); 
                }
            }

            private Dispatcher _that; 
        }
 
        private class WeakEventPreprocessMessage: WeakReference 
        {
            ///  
            ///     Critical: This code calls attaches an arbitrary window
            ///     to the call path for the component dispatcher call back
            /// 
            [SecurityCritical] 
            public WeakEventPreprocessMessage(HwndSource source): base(source)
            { 
                ComponentDispatcher.ThreadPreprocessMessage += 
                                new ThreadMessageEventHandler(this.OnPreprocessMessage);
            } 

            /// 
            ///     Critical: This can be used to spoof and change input
            ///  
            [SecurityCritical]
            public void OnPreprocessMessage(ref MSG msg, ref bool handled) 
            { 
                HwndSource source = this.Target as HwndSource;
                if(null != source) 
                {
                    source.OnPreprocessMessageThunk(ref msg, ref handled);
                }
                else 
                {
                    Dispose(); 
                } 
            }
 

            /// 
            ///     Critical:This code calls into ComponentDispatcher
            ///     to disconnect a listener 
            ///     TreatAsSafe: This code is ok to call
            ///  
            [SecurityCritical,SecurityTreatAsSafe] 
            public void Dispose()
            { 
                ComponentDispatcher.ThreadPreprocessMessage -=
                                new ThreadMessageEventHandler(this.OnPreprocessMessage);
            }
        } 

#endregion WeakEventHandlers 
 
        private object                      _constructionParameters; // boxed HwndSourceParameters
 
        private bool                        _isDisposed = false;
        private bool                        _isDisposing = false;
        private bool                        _inRealHwndDispose = false;
        private bool                        _adjustSizingForNonClientArea; 
        private bool                        _myOwnUpdate;
        private bool                        _isWindowInMinimizeState = false; 
 
        private int                         _registeredDropTargetCount;
 
        private SizeToContent               _sizeToContent = SizeToContent.Manual;
        private Size?                       _previousSize;

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical. 
        ///  
        [SecurityCritical]
        private HwndWrapper                 _hwndWrapper; 

        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical. 
        /// 
        [SecurityCritical] 
        private HwndTarget                  _hwndTarget; 

        private SecurityCriticalDataForSet                      _rootVisual; 

        private ArrayList                   _hooks;
        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data is considered critical.
        ///  
        private SecurityCriticalDataClass      _mouse; 
        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data is considered critical.
        /// 
        private SecurityCriticalDataClass   _keyboard;
        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical. 
        ///  
        private SecurityCriticalDataClass     _stylus;
 
        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical.
        ///  
        private SecurityCriticalDataClass _appCommand;
 
        WeakEventDispatcherShutdown _weakShutdownHandler; 
        WeakEventPreprocessMessage _weakPreprocessMessageHandler;
 
        private static System.LocalDataStoreSlot _threadSlot;

        private MSG                         _lastKeyboardMessage;
        private List _keyboardInputSinkChildren; 

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data can be used to spoof input
        ///  
        [SecurityCritical]
        private IKeyboardInputSite          _keyboardInputSite = null;

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input 
        ///  
        [SecurityCritical]
        private HwndWrapperHook             _layoutHook; 

        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input 
        /// 
        [SecurityCritical] 
        private HwndWrapperHook             _inputHook; 

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input
        /// 
        [SecurityCritical] 
        private HwndWrapperHook             _hwndTargetHook;
 
        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input 
        /// 
        [SecurityCritical]
        private HwndWrapperHook             _publicHook;
 
        // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
        // 
        // Avalon relies on the policy that if you handle the KeyDown 
        // event, you will not get the TextInput events caused by
        // pressing the key.  This is generally implemented because the 
        // message pump calls ComponentDispatcher.RaiseThreadMessage and
        // we return whether or not the WM_KEYDOWN message was handled,
        // and the message pump will only call TranslateMessage() if the
        // WM_KEYDOWN was not handled.  However, naive message pumps don't 
        // call ComponentDispatcher.RaiseThreadMessage, and always call
        // TranslateMessage, so the WM_CHAR is generated no matter what. 
        // The best work around we could think of was to eat the WM_CHAR 
        // messages and not report them to Avalon.
        // 
        [ThreadStatic]
        internal static bool _eatCharMessages; // used from HwndKeyboardInputProvider
        internal static int _msgEnableCharMessages;
 
    }
} 

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