PointUtil.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Shared / MS / Internal / PointUtil.cs / 1305600 / PointUtil.cs

                            using System; 
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows; 
using System.Windows.Media;
using System.Windows.Interop; 
 
using MS.Win32;
 
#if PRESENTATION_CORE
using MS.Internal.PresentationCore;
#else
#error There is an attempt to use this class from an unexpected assembly. 
#endif
 
namespace MS.Internal 
{
     ///  
     ///    A utility class for converting Point and Rect data between co-ordinate spaces
     /// 
     /// 
     ///    To avoid confusion, Avalon based Point and Rect variables are prefixed with 
     ///    "point" and "rect" respectively, whereas Win32 POINT and RECT variables are
     ///    prefixed with "pt" and "rc" respectively. 
     ///  
    [FriendAccessAllowed] // Built into Core, also used by Framework.
    internal static class PointUtil 
    {
        /// 
        ///     Convert a point from "client" coordinate space of a window into
        ///     the coordinate space of the root element of the same window. 
        /// 
        ///  
        ///    Critical: This code accesses presentationSource 
        ///    TreatAsSafe: Transforming a Point is considered safe.
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        public static Point ClientToRoot(Point point, PresentationSource presentationSource)
        {
            bool success = true; 
            return TryClientToRoot(point, presentationSource, true, out success);
        } 
 
        [SecurityCritical,SecurityTreatAsSafe]
        public static Point TryClientToRoot(Point point, PresentationSource presentationSource, bool throwOnError, out bool success) 
        {
            // Only do if we allow throwing on error or have a valid PresentationSource and CompositionTarget.
            if (throwOnError || (presentationSource != null && presentationSource.CompositionTarget != null && !presentationSource.CompositionTarget.IsDisposed))
            { 
                // Convert from pixels into measure units.
                point = presentationSource.CompositionTarget.TransformFromDevice.Transform(point); 
 
                //
 

                point = TryApplyVisualTransform(point, presentationSource.RootVisual, true, throwOnError, out success);
            }
            else 
            {
                success = false; 
                return new Point(0,0); 
            }
 
            return point;
        }

        ///  
        ///     Convert a point from the coordinate space of a root element of
        ///     a window into the "client" coordinate space of the same window. 
        ///  
        /// 
        ///    Critical: This code accesses presentationSource 
        ///    TreatAsSafe: Transforming a point is considered safe.
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        public static Point RootToClient(Point point, PresentationSource presentationSource) 
        {
            // 
 

            point = ApplyVisualTransform(point, presentationSource.RootVisual, false); 

            // Convert from measure units into pixels.
            point = presentationSource.CompositionTarget.TransformToDevice.Transform(point);
 
            return point;
        } 
 
        /// 
        ///     Convert a point from "above" the coordinate space of a 
        ///     visual into the the coordinate space "below" the visual.
        /// 
        public static Point ApplyVisualTransform(Point point, Visual v, bool inverse)
        { 
            bool success = true;
            return TryApplyVisualTransform(point, v, inverse, true, out success); 
        } 

        ///  
        ///     Convert a point from "above" the coordinate space of a
        ///     visual into the the coordinate space "below" the visual.
        /// 
        public static Point TryApplyVisualTransform(Point point, Visual v, bool inverse, bool throwOnError, out bool success) 
        {
            success = true; 
 
            // Notes:
            // 1) First of all the MIL should provide a way of transforming 
            //    a point from the window to the root element.
            // 2) A visual can currently have two properties that affect
            //    its coordinate space:
            //    A) Transform - any matrix 
            //    B) Offset - a simpification for just a 2D offset.
            // 3) In the future a Visual may have other properties that 
            //    affect its coordinate space, which is why the MIL should 
            //    provide this API in the first place.
            // 
            // The following code was copied from the MIL's TransformToAncestor
            // method on 12/16/2005.
            //
            if(v != null) 
            {
                Matrix m = GetVisualTransform(v); 
 
                if (inverse)
                { 
                    if(throwOnError || m.HasInverse)
                    {
                        m.Invert();
                    } 
                    else
                    { 
                        success = false; 
                        return new Point(0,0);
                    } 
                }

                point = m.Transform(point);
            } 

            return point; 
        } 

        ///  
        ///     Gets the matrix that will convert a point
        ///     from "above" the coordinate space of a visual
        ///     into the the coordinate space "below" the visual.
        ///  
        internal static Matrix GetVisualTransform(Visual v)
        { 
            if (v != null) 
            {
                Matrix m = Matrix.Identity; 

                Transform transform = VisualTreeHelper.GetTransform(v);
                if (transform != null)
                { 
                    Matrix cm = transform.Value;
                    m = Matrix.Multiply(m, cm); 
                } 

                Vector offset = VisualTreeHelper.GetOffset(v); 
                m.Translate(offset.X, offset.Y);

                return m;
            } 

            return Matrix.Identity; 
        } 

        ///  
        ///     Convert a point from "client" coordinate space of a window into
        ///     the coordinate space of the screen.
        /// 
        ///  
        ///     SecurityCritical: This code causes eleveation to unmanaged code via call to GetWindowLong
        ///     SecurityTreatAsSafe: This data is ok to give out 
        ///     validate all code paths that lead to this. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        public static Point ClientToScreen(Point pointClient, PresentationSource presentationSource)
        {
            // For now we only know how to use HwndSource.
            HwndSource inputSource = presentationSource as HwndSource; 
            if(inputSource == null)
            { 
                return pointClient; 
            }
            HandleRef handleRef = new HandleRef(inputSource, inputSource.CriticalHandle); 

            NativeMethods.POINT ptClient            = FromPoint(pointClient);
            NativeMethods.POINT ptClientRTLAdjusted = AdjustForRightToLeft(ptClient, handleRef);
 
            UnsafeNativeMethods.ClientToScreen(handleRef, ptClientRTLAdjusted);
 
            return ToPoint(ptClientRTLAdjusted); 
        }
 
        /// 
        ///     Convert a point from the coordinate space of the screen into
        ///     the "client" coordinate space of a window.
        ///  
        /// 
        ///    Critical: This code accesses presentationSource 
        ///    TreatAsSafe: Transforming a Point is considered safe. 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        internal static Point ScreenToClient(Point pointScreen, PresentationSource presentationSource)
        {
            // For now we only know how to use HwndSource.
            HwndSource inputSource = presentationSource as HwndSource; 
            if(inputSource == null)
            { 
                return pointScreen; 
            }
 
            HandleRef handleRef = new HandleRef(inputSource, inputSource.CriticalHandle);

            NativeMethods.POINT ptClient = FromPoint(pointScreen);
 
            SafeNativeMethods.ScreenToClient(handleRef, ptClient);
 
            ptClient = AdjustForRightToLeft(ptClient, handleRef); 

            return ToPoint(ptClient); 
        }

        /// 
        ///     Converts a rectangle from element co-ordinate space to that of the root visual 
        /// 
        ///  
        ///     The rectangle to be converted 
        /// 
        ///  
        ///     The element whose co-ordinate space you wish to convert from
        /// 
        /// 
        ///     The PresentationSource which hosts the specified Visual.  This is passed in for performance reasons. 
        /// 
        ///  
        ///     The rectangle in the co-ordinate space of the root visual 
        /// 
        ///  
        ///    Critical: This code accesses presentationSource
        ///    TreatAsSafe: Transforming a point is considered safe.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal static Rect ElementToRoot(Rect rectElement, Visual element, PresentationSource presentationSource)
        { 
            GeneralTransform    transformElementToRoot  = element.TransformToAncestor(presentationSource.RootVisual); 
            Rect                rectRoot                = transformElementToRoot.TransformBounds(rectElement);
 
            return rectRoot;
        }

        ///  
        ///     Converts a rectangle from root visual co-ordinate space to Win32 client
        ///  
        ///  
        ///     RootToClient takes into account device DPI settings to convert to/from Avalon's assumed 96dpi
        ///     and any "root level" transforms applied to the root such as "right-to-left" inversions. 
        /// 
        /// 
        ///     The rectangle to be converted
        ///  
        /// 
        ///     The PresentationSource which hosts the root visual.  This is passed in for performance reasons. 
        ///  
        /// 
        ///     The rectangle in Win32 client co-ordinate space 
        /// 
        /// 
        ///    Critical: This code accesses presentationSource
        ///    TreatAsSafe: Transforming a point is considered safe. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal static Rect RootToClient(Rect rectRoot, PresentationSource presentationSource) 
        {
            CompositionTarget   target                  = presentationSource.CompositionTarget; 
            Matrix              matrixRootTransform     = PointUtil.GetVisualTransform(target.RootVisual);
            Rect                rectRootUntransformed   = Rect.Transform(rectRoot, matrixRootTransform);
            Matrix              matrixDPI               = target.TransformToDevice;
            Rect                rectClient              = Rect.Transform(rectRootUntransformed, matrixDPI); 

            return rectClient; 
        } 

        ///  
        ///     Converts a rectangle from Win32 client co-ordinate space to Win32 screen
        /// 
        /// 
        ///  
        /// 
        ///     The rectangle to be converted 
        ///  
        /// 
        ///     The HwndSource corresponding to the Win32 window containing the rectangle 
        /// 
        /// 
        ///     The rectangle in Win32 screen co-ordinate space
        ///  
        /// 
        ///    Critical: UnsafeNativeMethods.ClientToScreen 
        ///    TreatAsSafe: Transforming a Point is considered safe. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal static Rect ClientToScreen(Rect rectClient, HwndSource hwndSource)
        {
            Point corner1 = ClientToScreen(rectClient.TopLeft, hwndSource);
            Point corner2 = ClientToScreen(rectClient.BottomRight, hwndSource); 
            return new Rect(corner1, corner2);
        } 
 
        /// 
        ///     Adjusts a POINT to compensate for Win32 RTL conversion logic 
        /// 
        /// 
        ///     MITIGATION: AVALON_RTL_AND_WIN32RTL
        /// 
        ///     When a window is marked with the WS_EX_LAYOUTRTL style, Win32
        ///     mirrors the coordinates during the various translation APIs. 
        /// 
        ///     Avalon also sets up mirroring transforms so that we properly
        ///     mirror the output since we render to DirectX, not a GDI DC. 
        ///
        ///     Unfortunately, this means that our coordinates are already mirrored
        ///     by Win32, and Avalon mirrors them again.  To work around this
        ///     problem, we un-mirror the coordinates from Win32 before hit-testing 
        ///     in Avalon.
        ///  
        ///  
        ///     The POINT to be adjusted
        ///  
        /// 
        ///     A HandleRef to the hwnd containing the point to be adjusted
        /// 
        ///  
        ///     The adjusted point
        ///  
        internal static NativeMethods.POINT AdjustForRightToLeft(NativeMethods.POINT pt, HandleRef handleRef) 
        {
            int windowStyle = SafeNativeMethods.GetWindowStyle(handleRef, true); 

            if(( windowStyle & NativeMethods.WS_EX_LAYOUTRTL ) == NativeMethods.WS_EX_LAYOUTRTL)
            {
                NativeMethods.RECT rcClient = new NativeMethods.RECT(); 
                SafeNativeMethods.GetClientRect(handleRef, ref rcClient);
                pt.x = rcClient.right - pt.x; 
            } 

            return pt; 
        }

        /// 
        ///     Adjusts a RECT to compensate for Win32 RTL conversion logic 
        /// 
        ///  
        ///     MITIGATION: AVALON_RTL_AND_WIN32RTL 
        ///
        ///     When a window is marked with the WS_EX_LAYOUTRTL style, Win32 
        ///     mirrors the coordinates during the various translation APIs.
        ///
        ///     Avalon also sets up mirroring transforms so that we properly
        ///     mirror the output since we render to DirectX, not a GDI DC. 
        ///
        ///     Unfortunately, this means that our coordinates are already mirrored 
        ///     by Win32, and Avalon mirrors them again.  To work around this 
        ///     problem, we un-mirror the coordinates from Win32 before hit-testing
        ///     in Avalon. 
        /// 
        /// 
        ///     The RECT to be adjusted
        ///  
        /// 
        ///  
        ///  
        ///     The adjusted rectangle
        ///  
        internal static NativeMethods.RECT AdjustForRightToLeft(NativeMethods.RECT rc, HandleRef handleRef)
        {
            int windowStyle = SafeNativeMethods.GetWindowStyle(handleRef, true);
 
            if(( windowStyle & NativeMethods.WS_EX_LAYOUTRTL ) == NativeMethods.WS_EX_LAYOUTRTL)
            { 
                NativeMethods.RECT rcClient = new NativeMethods.RECT(); 
                SafeNativeMethods.GetClientRect(handleRef, ref rcClient);
 
                int width   = rc.right - rc.left;       // preserve width
                rc.right    = rcClient.right - rc.left; // set right of rect to be as far from right of window as left of rect was from left of window
                rc.left     = rc.right - width;         // restore width by adjusting left and preserving right
            } 
            return rc;
        } 
 
        /// 
        ///     Converts a location from an Avalon Point to a Win32 POINT 
        /// 
        /// 
        ///     Rounds "double" values to the nearest "int"
        ///  
        /// 
        ///     The location as an Avalon Point 
        ///  
        /// 
        ///     The location as a Win32 POINT 
        /// 
        internal static NativeMethods.POINT FromPoint(Point point)
        {
            return new NativeMethods.POINT(DoubleUtil.DoubleToInt(point.X), DoubleUtil.DoubleToInt(point.Y)); 
        }
 
        ///  
        ///     Converts a location from a Win32 POINT to an Avalon Point
        ///  
        /// 
        ///     The location as a Win32 POINT
        /// 
        ///  
        ///     The location as an Avalon Point
        ///  
        internal static Point ToPoint(NativeMethods.POINT pt) 
        {
            return new Point(pt.x, pt.y); 
        }

        /// 
        ///     Converts a rectangle from an Avalon Rect to a Win32 RECT 
        /// 
        ///  
        ///     Rounds "double" values to the nearest "int" 
        /// 
        ///  
        ///     The rectangle as an Avalon Rect
        /// 
        /// 
        ///     The rectangle as a Win32 RECT 
        /// 
        internal static NativeMethods.RECT FromRect(Rect rect) 
        { 
            NativeMethods.RECT rc = new NativeMethods.RECT();
 
            rc.top      = DoubleUtil.DoubleToInt(rect.Y);
            rc.left     = DoubleUtil.DoubleToInt(rect.X);
            rc.bottom   = DoubleUtil.DoubleToInt(rect.Bottom);
            rc.right    = DoubleUtil.DoubleToInt(rect.Right); 

            return rc; 
        } 

        ///  
        ///     Converts a rectangle from a Win32 RECT to an Avalon Rect
        /// 
        /// 
        ///     The rectangle as a Win32 RECT 
        /// 
        ///  
        ///     The rectangle as an Avalon Rect 
        /// 
        internal static Rect ToRect(NativeMethods.RECT rc) 
        {
            Rect rect = new Rect();

            rect.X      = rc.left; 
            rect.Y      = rc.top;
            rect.Width  = rc.right  - rc.left; 
            rect.Height = rc.bottom - rc.top; 

            return rect; 
        }

    }
} 

 

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