Example #1
0
        //------------------------------------------------------
        //
        //  Public Methods
        //
        //------------------------------------------------------

        #region Public Methods

        // We will not always find the clickable point.   There are times when it would take so long 
        // to locate the point that it is just not worth it, so make a reason effort than quit.
        public static bool  HitTestForClickablePoint(AutomationElement el, out Point pt)
        {
            Rect rect = el.Current.BoundingRectangle;
            
            pt = new Point(0, 0);
            if (rect.Left >= rect.Right || rect.Top >= rect.Bottom)
                return false;    
            
            // if this is not on any monitor than there is no point in going on.  If the element is 
            // off the screen hit testing actually works and would end up returning a point offscreen.
            NativeMethods.RECT winRect = new NativeMethods.RECT((int)rect.Left, (int)rect.Top, (int)rect.Height, (int)rect.Bottom);
            if (SafeNativeMethods.MonitorFromRect( ref winRect, SafeNativeMethods.MONITOR_DEFAULTTONULL ) == IntPtr.Zero)
                return false;


            // try the center point first
            pt = new Point((rect.Left + rect.Right) / 2, (rect.Top + rect.Bottom) / 2);

            AutomationElement hitElement;
            if ( TryPoint( ref pt, el, out hitElement ) )
                return true;
            
            if ( IsTopLevelWindowObscuring( el, rect, hitElement ) )
                return false;
            
            // before we start hit testing more there are some control types that we know where the 
            // clickable point is or we know does not have a clickable point so take care of those here.
            if ( el.Current.ControlType == ControlType.ScrollBar )
                return false;

            // Try  the mid point of all four sides
            pt = new Point(rect.Left + (rect.Width /2),  rect.Top + 1);
            if ( TryPoint( ref pt, el ) )
                return true;
            
            pt = new Point(rect.Left + (rect.Width /2),  rect.Bottom - 1);
            if ( TryPoint( ref pt, el ) )
                return true;
            
            pt = new Point( rect.Left + 1, rect.Top + (rect.Height /2) );
            if ( TryPoint( ref pt, el) )
                return true;
            
            pt = new Point(  rect.Right - 1, rect.Top + (rect.Height /2) );
            if ( TryPoint( ref pt, el ) )
                return true;
            
            
            if ( TrySparsePattern( out pt, ref rect, el ) )
                return true;
            
            if ( TryLinePattern( out pt, ref rect, el ) )
                return true;
            
            return false;
        }
        override protected Rect GetBoundingRectangleCore()
        {
            Window window = (Window)Owner;
            Rect bounds = new Rect(0,0,0,0);
            
            if(!window.IsSourceWindowNull)
            {

                NativeMethods.RECT rc = new NativeMethods.RECT(0,0,0,0);
                IntPtr windowHandle = window.CriticalHandle;
                if(windowHandle != IntPtr.Zero) //it is Zero on a window that was just closed
                {
                    try { SafeNativeMethods.GetWindowRect(new HandleRef(null, windowHandle), ref rc); }
// Allow empty catch statements.
#pragma warning disable 56502
                    catch(Win32Exception) {}
// Disallow empty catch statements.
#pragma warning restore 56502
                }        
                bounds = new Rect(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
            }

            return bounds;
        }
        /// -------------------------------------------------------------------
        /// <summary>
        /// Get the window rect using the Win32 API GetWindowRect.  If there is
        /// a buddy control (ie. Spinner), then take the union of the element's 
        /// bounding rectangle, and the buddy controls bounding rectangle.
        /// </summary>
        /// -------------------------------------------------------------------
        private void TS_GetWin32GetWindowRect(AutomationElement element, out Rect rectObject, CheckType checktype)
        {
            NativeMethods.RECT rcObject = new NativeMethods.RECT();
            NativeMethods.RECT rcBuddy = new NativeMethods.RECT();

            Rect rectBuddy = new Rect();
            IntPtr intPtrElement = Helpers.CastNativeWindowHandleToIntPtr(element);

            if (intPtrElement == IntPtr.Zero)
                ThrowMe(checktype, "Could not get a window handle to the element");

            // Get the AutomationElement Win32 bounding rectangle
            SafeNativeMethods.GetWindowRect(intPtrElement, ref rcObject);
            rectObject = new Rect(rcObject.left, rcObject.top, rcObject.right - rcObject.left, rcObject.bottom - rcObject.top);

            // If this has a buddy control, get it and it's bounding rectangle
            IntPtr hwndBuddy = Helpers.SendMessage(intPtrElement, NativeMethods.UDM_GETBUDDY, IntPtr.Zero, IntPtr.Zero);
            if (hwndBuddy != IntPtr.Zero)
            {
                SafeNativeMethods.GetWindowRect(hwndBuddy, ref rcBuddy);
                rectBuddy = new Rect(rcBuddy.left, rcBuddy.top, rcBuddy.right - rcBuddy.left, rcBuddy.bottom - rcBuddy.top);
                rectObject = Rect.Union(rectBuddy, rectObject);
            }

            m_TestStep++;
        }
 internal static extern bool AdjustWindowRectExForDpi(
     [In][Out] ref NativeMethods.RECT lpRect,
     [In] int dwStyle,
     [In][MarshalAs(UnmanagedType.Bool)] bool bMenu,
     [In] int dwExStyle,
     [In] int dpi);
Example #5
0
                private NativeMethods.POINT GetWindowScreenLocation(FlowDirection flowDirection)
                {
                    Debug.Assert(IsSourceWindowNull != true, "IsSourceWindowNull cannot be true here");
                    NativeMethods.POINT pt = new NativeMethods.POINT(0, 0);
                    if (flowDirection == FlowDirection.RightToLeft)
                    {
                        NativeMethods.RECT rc = new NativeMethods.RECT(0, 0, 0, 0);

                        // with RTL window, GetClientRect returns reversed coordinates
                        SafeNativeMethods.GetClientRect(new HandleRef(this, CriticalHandle), ref rc);

                        // note that we use rc.right here for the RTL case and client to screen that point
                        pt = new NativeMethods.POINT(rc.right, rc.top);
                    }
                    UnsafeNativeMethods.ClientToScreen(new HandleRef(this, _sourceWindow.CriticalHandle), pt);

                    return pt;
                }
Example #6
0
        private void PossiblyDeactivate(IntPtr hwndCapture, bool stillActiveIfOverSelf)
        {
            // we may have been disposed by a re-entrant call (bug 1536643).
            // If so, there's nothing more to do.
            if (null == _source || null == _source.Value )
            {
                return;
            }

            if(_isDwmProcess)
            {
                return;
            }

            //Console.WriteLine("PossiblyDeactivate(" + hwndCapture + ")");

            // We are now longer active ourselves, but it is possible that the
            // window the mouse is going to intereact with is in the same
            // Dispatcher as ourselves.  If so, we don't want to deactivate the
            // mouse input stream because the other window hasn't activated it
            // yet, and it may result in the input stream "flickering" between
            // active/inactive/active.  This is ugly, so we try to supress the
            // uneccesary transitions.
            //
            IntPtr hwndToCheck = hwndCapture;
            if(hwndToCheck == IntPtr.Zero)
            {
                NativeMethods.POINT ptCursor = new NativeMethods.POINT();
                int messagePos = 0;
                try
                {
                    messagePos = SafeNativeMethods.GetMessagePos();
                }
                catch(System.ComponentModel.Win32Exception)
                {
                    System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetMessagePos failed!");
                }

                ptCursor.x = NativeMethods.SignedLOWORD(messagePos);
                ptCursor.y = NativeMethods.SignedHIWORD(messagePos);
                //Console.WriteLine("  GetMessagePos: ({0},{1})", ptCursor.x, ptCursor.y);

                try
                {
                    hwndToCheck = UnsafeNativeMethods.WindowFromPoint(ptCursor.x, ptCursor.y);
                }
                catch(System.ComponentModel.Win32Exception)
                {
                    System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: WindowFromPoint failed!");
                }

                if (!stillActiveIfOverSelf && hwndToCheck == _source.Value.CriticalHandle)
                {
                    hwndToCheck = IntPtr.Zero;
                }

                if(hwndToCheck != IntPtr.Zero)
                {
                    // We need to check if the point is over the client or
                    // non-client area.  We only care about being over the
                    // non-client area.
                    try
                    {
                        NativeMethods.RECT rcClient = new NativeMethods.RECT();
                        SafeNativeMethods.GetClientRect(new HandleRef(this,hwndToCheck), ref rcClient);
                        SafeNativeMethods.ScreenToClient(new HandleRef(this,hwndToCheck), ptCursor);

                        if(ptCursor.x < rcClient.left || ptCursor.x >= rcClient.right ||
                           ptCursor.y < rcClient.top || ptCursor.y >= rcClient.bottom)
                        {
                            // We are not over the non-client area.  We can bail out.
                            //Console.WriteLine("  No capture, mouse outside of client area.");
                            //Console.WriteLine("  Client Area: ({0},{1})-({2},{3})", rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
                            //Console.WriteLine("  Mouse: ({0},{1})", ptCursor.x, ptCursor.y);
                            hwndToCheck = IntPtr.Zero;
                        }
                    }
                    catch(System.ComponentModel.Win32Exception)
                    {
                        System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetClientRect or ScreenToClient failed!");
                    }
                }
            }

            // If the window the mouse is over is ours, we'll just let it activate
            // without deactivating the mouse input stream for this window.  This prevents
            // the mouse input stream from flickering.
            bool deactivate = !IsOurWindow(hwndToCheck);

            //Console.WriteLine("  Deactivate=" + deactivate);

            // Only deactivate the mouse input stream if needed.
            if(deactivate)
            {
                ReportInput(_source.Value.CriticalHandle,
                            InputMode.Foreground,
                            _msgTime,
                            RawMouseActions.Deactivate,
                            0,
                            0,
                            0);
            }
            else
            {
                // We are not deactivating the mouse input stream because the
                // window that is going to provide mouse input next is one of
                // our Avalon windows.  This optimization keeps the mouse input
                // stream from flickering by transitioning to null.
                //
                // But this window itself should not be active anymore.
                _active = false;
            }
        }
Example #7
0
        /// <summary>
        ///     Converts a rectangle from an Avalon Rect to a Win32 RECT
        /// </summary>
        /// <remarks>
        ///     Rounds "double" values to the nearest "int"
        /// </remarks>
        /// <param name="rect">
        ///     The rectangle as an Avalon Rect
        /// </param>
        /// <returns>
        ///     The rectangle as a Win32 RECT
        /// </returns>
        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;
        }
Example #8
0
        /// <summary>
        ///     Adjusts a POINT to compensate for Win32 RTL conversion logic
        /// </summary>
        /// <remarks>
        ///     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.
        /// </remarks>
        /// <param name="pt">
        ///     The POINT to be adjusted
        /// </param>
        /// <param name="handleRef">
        ///     A HandleRef to the hwnd containing the point to be adjusted
        /// </param>
        /// <returns>
        ///     The adjusted point
        /// </returns>
        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;
        }
        private void UpdateWindowPos(IntPtr lParam)
        {
            //
            // We need to update the window settings used by the render thread when
            // 1) The size or position of the render target needs to change
            // 2) The render target needs to be enabled or disabled.
            //
            // Further, we need to synchronize the render thread during sizing operations.
            // This is because some APIs that the render thread uses (such as
            // UpdateLayeredWindow) have the unintended side-effect of also changing the
            // window size.  We can't let the render thread and the UI thread fight
            // over setting the window size.
            //
            // Generally, Windows sends our window to messages that bracket the size
            // operation:
            // 1) WM_WINDOWPOSCHANGING
            //    Here we synchronize with the render thread, and ask the render thread
            //    to not render to this window for a while.
            // 2) WM_WINDOWPOSCHANGED
            //    This is after the window size has actually been changed, so we tell
            //    the render thread that it can render to the window again.
            //
            // However, there are complications.  Sometimes Windows will send a
            // WM_WINDOWPOSCHANGING without sending a WM_WINDOWPOSCHANGED.  This happens
            // when the window size is not really going to change.  Also note that
            // more than just size/position information is provided by these messages.
            // We'll get these messages when nothing but the z-order changes for instance.
            //


            //
            // The first order of business is to determine if the render target
            // size or position changed.  If so, we need to pass this information to
            // the render thread.
            //
            NativeMethods.WINDOWPOS windowPos = (NativeMethods.WINDOWPOS)UnsafeNativeMethods.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS));
            bool isMove = (windowPos.flags & NativeMethods.SWP_NOMOVE) == 0;
            bool isSize = (windowPos.flags & NativeMethods.SWP_NOSIZE) == 0;
            bool positionChanged = (isMove || isSize);
            if (positionChanged)
            {
                //
                // We have found that sometimes we get told that the size or position
                // of the window has changed, when it really hasn't.  So we double
                // check here.  This is critical because we won't be given a
                // WM_WINDOWPOSCHANGED unless the size or position really had changed.
                //
                if (!isMove)
                {
                    // This is just to avoid any possible integer overflow problems.
                    windowPos.x = windowPos.y = 0;
                }
                if (!isSize)
                {
                    // This is just to avoid any possible integer overflow problems.
                    windowPos.cx = windowPos.cy = 0;
                }

                //
                // WINDOWPOS stores the window coordinates relative to its parent.
                // If the parent is NULL, then these are already screen coordinates.
                // Otherwise, we need to convert to screen coordinates.
                //
                NativeMethods.RECT windowRectInScreenCoords = new NativeMethods.RECT(windowPos.x, windowPos.y, windowPos.x + windowPos.cx, windowPos.y + windowPos.cy);
                IntPtr hwndParent = UnsafeNativeMethods.GetParent(new HandleRef(null, windowPos.hwnd));
                if(hwndParent != IntPtr.Zero)
                {
                    SafeSecurityHelper.TransformLocalRectToScreen(new HandleRef(null, hwndParent), ref windowRectInScreenCoords);
                }

                if (!isMove)
                {
                    // We weren't actually moving, so the WINDOWPOS structure
                    // did not contain valid (x,y) information.  Just use our
                    // old values.
                    int width = (windowRectInScreenCoords.right - windowRectInScreenCoords.left);
                    int height = (windowRectInScreenCoords.bottom - windowRectInScreenCoords.top);
                    windowRectInScreenCoords.left = _hwndWindowRectInScreenCoords.left;
                    windowRectInScreenCoords.right = windowRectInScreenCoords.left + width;
                    windowRectInScreenCoords.top = _hwndWindowRectInScreenCoords.top;
                    windowRectInScreenCoords.bottom = windowRectInScreenCoords.top + height;
                }

                if (!isSize)
                {
                    // We weren't actually sizing, so the WINDOWPOS structure
                    // did not contain valid (cx,cy) information.  Just use our
                    // old values.
                    int width = (_hwndWindowRectInScreenCoords.right - _hwndWindowRectInScreenCoords.left);
                    int height = (_hwndWindowRectInScreenCoords.bottom - _hwndWindowRectInScreenCoords.top);

                    windowRectInScreenCoords.right = windowRectInScreenCoords.left + width;
                    windowRectInScreenCoords.bottom = windowRectInScreenCoords.top + height;
                }

                positionChanged = (   _hwndWindowRectInScreenCoords.left != windowRectInScreenCoords.left
                                   || _hwndWindowRectInScreenCoords.top != windowRectInScreenCoords.top
                                   || _hwndWindowRectInScreenCoords.right != windowRectInScreenCoords.right
                                   || _hwndWindowRectInScreenCoords.bottom != windowRectInScreenCoords.bottom);
            }


            //
            // The second order of business is to determine whether or not the render
            // target should be enabled.  If we are disabling the render target, then
            // we need to synchronize with the render thread.  Basically,
            // a WM_WINDOWPOSCHANGED always enables the render target it the window is
            // visible.  And a WM_WINDOWPOSCHANGING will disable the render target
            // unless it is not really a size/move, in which case we will not be sent
            // a WM_WINDOWPOSCHANGED, so we can't disable the render target.
            //
            bool enableRenderTarget = SafeNativeMethods.IsWindowVisible(_hWnd.MakeHandleRef(this));
            if(enableRenderTarget)
            {
                if(_windowPosChanging && (positionChanged))
                {
                    enableRenderTarget = false;
                }
            }


            if (positionChanged || (enableRenderTarget != _isRenderTargetEnabled))
            {
                UpdateWindowSettings(enableRenderTarget);
            }
        }
        override protected Rect GetBoundingRectangleCore()
        {
            Rect bounds = new Rect(0,0,0,0);
            
            IntPtr hwnd = this.Hwnd;
            if(hwnd != IntPtr.Zero)
            {

                NativeMethods.RECT rc = new NativeMethods.RECT(0,0,0,0);
                try 
                { 
                    //This method elevates via SuppressUnmanadegCodeSecurity and throws Win32Exception on GetLastError
                    SafeNativeMethods.GetWindowRect(new HandleRef(null, hwnd), ref rc); 
                }
// Allow empty catch statements.
#pragma warning disable 56502
                catch(Win32Exception) {}
// Disallow empty catch statements.
#pragma warning restore 56502

                bounds = new Rect(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
            }

            return bounds;
        }
Example #11
0
 internal static extern bool GetWindowRect(IntPtr hwnd, ref NativeMethods.RECT rect);
        //------------------------------------------------------
        //
        //  Interface ITransformProvider
        //
        //------------------------------------------------------

        #region Interface ITransformProvider

        void ITransformProvider.Move( double x, double y )
        {
            if ( ! ((ITransformProvider)this).CanMove )
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));

            int extendedStyle = GetWindowExStyle();
            if ( IsBitSet(extendedStyle, SafeNativeMethods.WS_EX_MDICHILD) )
            {
                // we always deal in screen pixels.  But if its an MDI window it interprets these as
                // client pixels so convert them to get the expected results.
                NativeMethods.POINT point = new NativeMethods.POINT((int)x, (int)y);
                NativeMethods.HWND hwndParent = SafeNativeMethods.GetAncestor(NativeMethods.HWND.Cast(_hwnd), SafeNativeMethods.GA_PARENT);
                if (!MapWindowPoints(NativeMethods.HWND.NULL, hwndParent, ref point, 1))
                {
                    throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
                }
                x = point.x;
                y = point.y;

                // Make sure the MDI child stays on the parents client area.
                NativeMethods.RECT currentRect = new NativeMethods.RECT();
                if (!Misc.GetWindowRect(_hwnd, out currentRect))
                {
                    throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
                }
                int currentHeight = currentRect.bottom - currentRect.top;
                int currentWidth = currentRect.right - currentRect.left;

                int dx = SafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CXHSCROLL);
                int dy = SafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CYHSCROLL);

                // If to far to the left move right edge to be visible.
                // Move the left edge the absalute differance of the right to the origin plus a little more to be visible.
                if (x + currentWidth < 0)
                {
                    x += ((x + currentWidth) * -1 + dx);
                }
                // If to far off the top move bottom edge down to be visible.
                // Move the top edge the absalute differance of the bottom to the origin plus a little more to be visible.
                if (y + currentHeight < 0)
                {
                    y += ((y + currentHeight) * -1 + dy);
                }

                NativeMethods.RECT parentRect = new NativeMethods.RECT();
                if (!Misc.GetClientRect(hwndParent, out parentRect))
                {
                    throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
                }
                // If to far to the right move left edge to be visible.
                // Move the left edge back the diffance of it and the parent's client area right side plus a little more to be visible.
                if (x > parentRect.right)
                {
                    x -= (x - parentRect.right + dx);
                }
                // If to far off the bottome move top edge down to be visible.
                // Move the top edge up the diffance of it and the parent's client area bottom side plus a little more to be visible.
                if (y > parentRect.bottom)
                {
                    y -= (y - parentRect.bottom + dy);
                }
            }

            // position the window keeping the zorder the same and not resizing.
            // We do this first so that the window is moved in terms of screen coordinates.
            // The WindowPlacement APIs take in to account the workarea which ends up
            // putting the window in the wrong place
            if (!Misc.SetWindowPos(_hwnd, NativeMethods.HWND.NULL, (int)x, (int)y, 0, 0, UnsafeNativeMethods.SWP_NOSIZE | UnsafeNativeMethods.SWP_NOZORDER | UnsafeNativeMethods.SWP_NOACTIVATE))
            {
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            }

            UnsafeNativeMethods.WINDOWPLACEMENT wp = new UnsafeNativeMethods.WINDOWPLACEMENT();
            wp.length = Marshal.SizeOf(typeof(UnsafeNativeMethods.WINDOWPLACEMENT));

            // get the WINDOWPLACEMENT information.  This includes the coordinates in
            // terms of the workarea.
            if (!Misc.GetWindowPlacement(_hwnd, ref wp))
            {
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            }

            int style = GetWindowStyle();
            if (style == 0)
            {
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            }
            if ( IsBitSet(style, SafeNativeMethods.WS_MINIMIZE) )
            {
                // If the window is minimized the parameters have to be setup differently
                wp.ptMinPosition.y = (int) y;
                wp.ptMinPosition.x = (int) x;
                wp.flags = UnsafeNativeMethods.WPF_SETMINPOSITION;

                // Use SetWindowPlacement to move the window because it handles the case where the
                // window is move completly off the screen even in the multi-mon case.  If this happens
                // it will place the window on the primary monitor at a location closest to the taget.
                if (!Misc.SetWindowPlacement(_hwnd, ref wp))
                {
                    throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
                }
            }
            else
            {
                NativeMethods.RECT currentRect = new NativeMethods.RECT();

                if (!Misc.GetWindowRect(_hwnd, out currentRect))
                {
                    throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
                }

                // Use SetWindowPlacement to move the window because it handles the case where the
                // window is move completly off the screen even in the multi-mon case.  If this happens
                // it will place the window on the primary monitor at a location closest to the taget.
                if (!Misc.SetWindowPlacement(_hwnd, ref wp))
                {
                    throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
                }

                // check to make sure SetWindowPlacement has not changed the size of our window
                // There may be a bug in SetWindowPlacement.
                int currentHeight = currentRect.bottom - currentRect.top;
                int currentWidth = currentRect.right - currentRect.left;

                if (!Misc.GetWindowPlacement(_hwnd, ref wp))
                {
                    throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
                }

                int newHeight = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
                int newWidth = wp.rcNormalPosition.right -wp.rcNormalPosition.left;

                if ( currentHeight != newHeight || currentWidth != newWidth )
                {
                    wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + currentHeight;
                    wp.rcNormalPosition.right = wp.rcNormalPosition.left + currentWidth;

                    if (!Misc.SetWindowPlacement(_hwnd, ref wp))
                    {
                        throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
                    }
                }
            }
        }
        // Get the child window at the specified point.
        // Returns IntPtr.NULL on error; returns original window if point is not
        // on any child window.
        // When the returned window is a child, the out param isClientArea indicates
        // whether the returned point is on the client area of the returned HWND.
        private static NativeMethods.HWND ChildWindowFromPoint( NativeMethods.HWND hwnd, double x, double y, out bool isClientArea )
        {
            NativeMethods.HWND hBestFitTransparent = NativeMethods.HWND.NULL;
            NativeMethods.RECT rcBest = new NativeMethods.RECT();
            isClientArea = true;

            IntPtr hrgn = Misc.CreateRectRgn(0, 0, 0, 0); // NOTE: Must be deleted before returning
            if (hrgn == IntPtr.Zero)
            {
                return NativeMethods.HWND.NULL;
            }

            // Infinite looping is 'possible' (though unlikely) when
            // using GetWindow(...NEXT), so we counter-limit this loop...
            int SanityLoopCount = 1024;
            for (NativeMethods.HWND hChild = Misc.GetWindow(hwnd, SafeNativeMethods.GW_CHILD);
                hChild != NativeMethods.HWND.NULL && --SanityLoopCount > 0 ;
                hChild = Misc.GetWindow(hChild, SafeNativeMethods.GW_HWNDNEXT))
            {
                // Skip invisible...
                if( ! IsWindowReallyVisible( hChild ) )
                    continue;

                // Check for rect...
                NativeMethods.RECT rc = new NativeMethods.RECT();
                if (!Misc.GetWindowRect(hChild, out rc))
                {
                    continue;
                }

                // If on Vista, convert the incoming physical screen coords to hwndChild-relative
                // logical coords before using them in [logical] rect comparisons...
                double xLogical = x;
                double yLogical = y;
                if (Environment.OSVersion.Version.Major >= 6)
                {
                    NativeMethods.HWND hwndTopLevel = SafeNativeMethods.GetAncestor(hChild, SafeNativeMethods.GA_ROOT);
                    NativeMethods.POINT pt = new NativeMethods.POINT((int)x, (int)y);
                    try
                    {
                        SafeNativeMethods.PhysicalToLogicalPoint(hwndTopLevel, ref pt);
                        xLogical = pt.x;
                        yLogical = pt.y;
                    }
                    catch (EntryPointNotFoundException)
                    {
                        // Ignore.
                    }
                }

                if(!PtInRect(rc, xLogical, yLogical))
                {
                    continue;
                }

                // Skip disabled child windows with other controls beneath it.
                // (only a few places actually use this,
                // eg. the Date&Time properties window, which has a disabled edit window
                // over the edits/static for the time components - see WinClient#856699)
                int style = GetWindowStyle(hChild);
                if ((style & SafeNativeMethods.WS_CHILD) != 0
                 && (style & SafeNativeMethods.WS_DISABLED) != 0)
                {
                    int x1 = (rc.left + rc.right) / 2;
                    int y1 = (rc.top + rc.bottom) / 2;
                    IntPtr hwndCompare = UnsafeNativeMethods.WindowFromPhysicalPoint(x1, y1);
                    // The WindowFromPoint function does not retrieve a handle to a hidden or disabled window,
                    // even if the point is within the window.  So we should either get the parents hwnd or
                    // the controls hwnd underneath the disabled control, if one exsists.
                    // 


                    if (hwndCompare != (IntPtr)hwnd)
                    {
                        // This means that there is another child under `the disabled child, so we want to exclude
                        // `the disabled child high in the z-order.
                        continue;
                    }
                }

                // Check for transparent layered windows (eg as used by menu and tooltip shadows)
                // (Note that WS_EX_TRANSPARENT has a specific meaning when used with WS_EX_LAYERED
                // that is different then when it is used alone, so we must check both flags
                // together.)
                int exStyle = GetWindowExStyle(hChild);
                if( ( exStyle & SafeNativeMethods.WS_EX_LAYERED ) != 0
                  && ( exStyle & SafeNativeMethods.WS_EX_TRANSPARENT ) != 0 )
                {
                    continue;
                }

                // If window is using a region (eg. Media Player), check whether
                // point is in it...
                if (SafeNativeMethods.GetWindowRgn(hChild.h, hrgn) == SafeNativeMethods.COMPLEXREGION)
                {
                    // hrgn is relative to window (not client or screen), so offset point appropriately...
                    if (!SafeNativeMethods.PtInRegion(hrgn, (int)xLogical - rc.left, (int)yLogical - rc.top))
                    {
                        continue;
                    }
                }

                // Try for transparency and/or non-client areas:
                IntPtr lr = Misc.SendMessageTimeout( hChild, UnsafeNativeMethods.WM_NCHITTEST, IntPtr.Zero, MAKELPARAM( (int)x, (int)y ) );
                if( lr == UnsafeNativeMethods.HTTRANSPARENT )
                {
                    // For reasons best known to the writers of USER, statics - used
                    // as labels - claim to be transparent. So that we do hit-test
                    // to these, we remember the hwnd here, so if nothing better
                    // comes along, we'll use this.

                    // If we come accross two or more of these, we remember the
                    // one that fits inside the other - if any. That way,
                    // we hit-test to siblings 'within' siblings - eg. statics in
                    // a groupbox.

                    if( hBestFitTransparent == NativeMethods.HWND.NULL )
                    {
                        hBestFitTransparent = hChild;
                        if (!Misc.GetWindowRect(hChild, out rcBest))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        // Is this child within the last remembered transparent?
                        // If so, remember it instead.
                        NativeMethods.RECT rcChild = new NativeMethods.RECT();
                        if (!Misc.GetWindowRect(hChild, out rcChild))
                        {
                            continue;
                        }
                        if( Rect1InRect2( rcChild, rcBest ) )
                        {
                            hBestFitTransparent = hChild;
                            rcBest = rcChild;
                        }
                    }

                    continue;
                }

                // Got the window!

                // Using the hit-test result and compairing against HTCLIENT is not good enough.  The Shell_TrayWnd control,
                // i.e. the task bar, will never returns a value of HTCLIENT, so check to see if the point is in the client area.
                NativeMethods.RECT rcClient = new NativeMethods.RECT();
                if (!Misc.GetClientRect(hChild, out rcClient) ||
                    !MapWindowPoints(hChild, NativeMethods.HWND.NULL, ref rcClient, 2) ||
                    !PtInRect(rcClient, xLogical, yLogical))
                {
                    isClientArea = false;
                }

                Misc.DeleteObject(hrgn); // finished with region
                return hChild;
            }

            Misc.DeleteObject(hrgn); // finished with region

            if( SanityLoopCount == 0 )
            {
                Debug.Assert(false, "too many children or inf loop?");
                return NativeMethods.HWND.NULL;
            }

            // Did we find a transparent (eg. a static) on our travels? If so, since
            // we couldn't find anything better, may as well use it.
            if( hBestFitTransparent != NativeMethods.HWND.NULL )
            {
                return hBestFitTransparent;
            }

            // Otherwise return the original window (not NULL!) if no child found...
            return hwnd;
        }
Example #14
0
            internal Rect GetParentWindowRect()
            {
                NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, 0, 0);

                IntPtr parent = ParentHandle;
                if (parent != IntPtr.Zero)
                {
                    SafeNativeMethods.GetClientRect(new HandleRef(null, parent), ref rect);
                }

                return PointUtil.ToRect(rect);
            }
Example #15
0
        // Paramter: Point p should be the most interesting point of a pop up positioning.  The top left.
        // Return the maximum boundingRect for the popup.
        // If this is not a child-popup
        //      and the Point p passed in is inside of the Work Area then return the monitor work area rect
        //          A tooltip opened above the taskbar will never display over/under the taskbar.
        //          To accomodate this the work area of the screen is returned to allow the pop up to
        //          respect the reserved area of the teskbar.
        //       and the Point p passed in is outside of the work area then return the monitor rect
        //          this can happen If the program is an appbar program (http://msdn.microsoft.com/en-us/library/cc144177(VS.85).aspx)
        //          and the tooltip is in the area removed from the work area.  In this case the tooltip can
        //          be placed without regard for the work area bounds.
        // Else this is the BoundingRect of either the placement target's window or the parent of the popup's window.
        private Rect GetScreenBounds(Rect boundingBox, Point p)
        {
            if (_secHelper.IsChildPopup)
            {
                // The "monitor" is the main window for child windows.
                return _secHelper.GetParentWindowRect();
            }

            NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, 0, 0);

            NativeMethods.RECT nativeBounds = PointUtil.FromRect(boundingBox);
            IntPtr monitor = SafeNativeMethods.MonitorFromRect(ref nativeBounds, NativeMethods.MONITOR_DEFAULTTONEAREST);

            if (monitor != IntPtr.Zero)
            {
                NativeMethods.MONITORINFOEX monitorInfo = new NativeMethods.MONITORINFOEX();

                monitorInfo.cbSize = Marshal.SizeOf(typeof(NativeMethods.MONITORINFOEX));
                SafeNativeMethods.GetMonitorInfo(new HandleRef(null, monitor), monitorInfo);

                //If this is a pop up for a menu or ToolTip then respect the work area if opening in the work area.
                if (((this.Child is MenuBase)
                    || (this.Child is ToolTip)
                    || (this.TemplatedParent is MenuItem))
                    && ((p.X >= monitorInfo.rcWork.left)
                        && (p.X <= monitorInfo.rcWork.right)
                        && (p.Y >= monitorInfo.rcWork.top)
                        && (p.Y <= monitorInfo.rcWork.bottom)))
                {
                    // Context Menus, MenuItems, and ToolTips shouldn't go over the Taskbar
                    rect = monitorInfo.rcWork;
                }
                else
                {
                    rect = monitorInfo.rcMonitor;
                }
            }

            return PointUtil.ToRect(rect);

        }
        private void DoPaint()
        {
            NativeMethods.PAINTSTRUCT ps = new NativeMethods.PAINTSTRUCT();
            NativeMethods.HDC hdc;

            HandleRef handleRef = new HandleRef(this, _hWnd);
            hdc.h = UnsafeNativeMethods.BeginPaint(handleRef, ref ps);
            int retval = UnsafeNativeMethods.GetWindowLong(handleRef, NativeMethods.GWL_EXSTYLE);

            NativeMethods.RECT rcPaint = new NativeMethods.RECT(ps.rcPaint_left, ps.rcPaint_top, ps.rcPaint_right, ps.rcPaint_bottom);

            //
            // If we get a BeginPaint with an empty rect then check
            // if this is a special layered, non-redirected window
            // which would mean we need to do a full paint when it
            // won't cause a problem.
            //
            if (rcPaint.IsEmpty
                && ((retval & NativeMethods.WS_EX_LAYERED) != 0)
                && !UnsafeNativeMethods.GetLayeredWindowAttributes(_hWnd.MakeHandleRef(this), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
                && !_isSessionDisconnected
                && !_isMinimized
                && (!_isSuspended || (UnsafeNativeMethods.GetSystemMetrics(SM.REMOTESESSION) != 0))) // 
                                                                                                     // notifications for the server monitor are being broad-casted when the
                                                                                                     // machine is in a non-local TS session. See Dev10 bug for more details.
            {
                rcPaint = new NativeMethods.RECT(
                          0,
                          0,
                          _hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left,
                          _hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top);
            }

            AdjustForRightToLeft(ref rcPaint, handleRef);

            if (!rcPaint.IsEmpty)
            {
                InvalidateRect(rcPaint);
            }

            UnsafeNativeMethods.EndPaint(_hWnd.MakeHandleRef(this), ref ps);
        }
        private void GetWindowRectsInScreenCoordinates()
        {
            NativeMethods.RECT rcClient = new NativeMethods.RECT();

            //
            // Get the window and client rectangles
            //

            SafeNativeMethods.GetWindowRect(_hWnd.MakeHandleRef(this), ref _hwndWindowRectInScreenCoords);
            SafeNativeMethods.GetClientRect(_hWnd.MakeHandleRef(this), ref rcClient);


            NativeMethods.POINT ptClientTopLeft = new NativeMethods.POINT(rcClient.left, rcClient.top);
            UnsafeNativeMethods.ClientToScreen(_hWnd.MakeHandleRef(this), ptClientTopLeft);

            NativeMethods.POINT ptClientBottomRight = new NativeMethods.POINT(rcClient.right, rcClient.bottom);
            UnsafeNativeMethods.ClientToScreen(_hWnd.MakeHandleRef(this), ptClientBottomRight);

            if(ptClientBottomRight.x >= ptClientTopLeft.x)
            {
                _hwndClientRectInScreenCoords.left = ptClientTopLeft.x;
                _hwndClientRectInScreenCoords.right = ptClientBottomRight.x;
            }
            else
            {
                // RTL windows will cause the right edge to be on the left...
                _hwndClientRectInScreenCoords.left = ptClientBottomRight.x;
                _hwndClientRectInScreenCoords.right = ptClientTopLeft.x;
            }

            if(ptClientBottomRight.y >= ptClientTopLeft.y)
            {
                _hwndClientRectInScreenCoords.top = ptClientTopLeft.y;
                _hwndClientRectInScreenCoords.bottom = ptClientBottomRight.y;
            }
            else
            {
                // RTL windows will cause the right edge to be on the left...
                // This doesn't affect top/bottom, but the code should be symmetrical.
                _hwndClientRectInScreenCoords.top = ptClientBottomRight.y;
                _hwndClientRectInScreenCoords.bottom = ptClientTopLeft.y;
            }

            // 
        }
 public static extern bool GetClientRect(NativeMethods.HWND hwnd, out NativeMethods.RECT rc);
 public static extern bool GetWindowRect(NativeMethods.HWND hwnd, out NativeMethods.RECT rc);
Example #20
0
 public static extern bool IntGetClientRect(HandleRef hWnd, [In, Out] ref NativeMethods.RECT rect);
Example #21
0
        /// <summary>
        ///     Adjusts a RECT to compensate for Win32 RTL conversion logic
        /// </summary>
        /// <remarks>
        ///     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.
        /// </remarks>
        /// <param name="rc">
        ///     The RECT to be adjusted
        /// </param>
        /// <param name="handleRef">
        /// </param>
        /// <returns>
        ///     The adjusted rectangle
        /// </returns>
        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;
        }
Example #22
0
 public static extern bool IntAdjustWindowRectEx(ref NativeMethods.RECT lpRect, int dwStyle, bool bMenu, int dwExStyle);
Example #23
0
        private bool ReportInput(
            IntPtr hwnd,
            InputMode mode,
            int timestamp,
            RawMouseActions actions,
            int x,
            int y,
            int wheel)
        {
            // if there's no HwndSource, we shouldn't get here.  But just in case...
            Debug.Assert(null != _source && null != _source.Value);
            if (_source == null || _source.Value == null)
            {
                return false;
            }

            PresentationSource source = _source.Value;
            CompositionTarget ct = source.CompositionTarget;

            // Input reports should only be generated if the window is still valid.
            if(_site == null || source.IsDisposed || ct == null )
            {
                if(_active)
                {
                    // We are still active, but the window is dead.  Force a deactivate.
                    actions = RawMouseActions.Deactivate;
                }
                else
                {
                    return false;
                }
            }

            if((actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate)
            {
                // Stop tracking the mouse since we are deactivating.
                StopTracking(hwnd);

                _active = false;
            }
            else if((actions & RawMouseActions.CancelCapture) == RawMouseActions.CancelCapture)
            {
                // We have lost capture, but don't do anything else.
            }
            else if(!_active && (actions & RawMouseActions.VerticalWheelRotate) == RawMouseActions.VerticalWheelRotate)
            {
                // report mouse wheel events as if they came from the window that
                // is under the mouse (even though they are reported to the window
                // with keyboard focus)
                MouseDevice mouse = _site.Value.CriticalInputManager.PrimaryMouseDevice;
                if (mouse != null && mouse.CriticalActiveSource != null)
                {
                    source = mouse.CriticalActiveSource;
                }
            }
            else
            {
                // If we are not active, we need to activate first.
                if(!_active)
                {
                    // But first, check for "spurious" mouse events...
                    //
                    // Sometimes we get a mouse move for window "A" AFTER another
                    // window ("B") has become active.  This would cause "A" to think
                    // that it is active, and to tell Avalon. Now both "A" and "B" think
                    // they are active, and Avalon thinks "A" is, but REALLY, "B" is.
                    //
                    // Confused yet?
                    //
                    // To avoid this, if this window ("A") gets a mouse move,
                    // we verify that either "A" has capture, or the mouse is over "A"

                    IntPtr hwndToCheck = SafeNativeMethods.GetCapture();
                    if(hwnd != hwndToCheck)
                    {
                        // If we get this far, "A" does NOT have capture
                        // - now ensure mouse is over "A"
                        NativeMethods.POINT ptCursor = new NativeMethods.POINT();
                        try
                        {
                            UnsafeNativeMethods.GetCursorPos(ptCursor);
                        }
                        catch(System.ComponentModel.Win32Exception)
                        {
                            // Sometimes Win32 will fail this call, such as if you are
                            // not running in the interactive desktop.  For example,
                            // a secure screen saver may be running.
                            System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetCursorPos failed!");
                        }

                        try
                        {
                            hwndToCheck = UnsafeNativeMethods.WindowFromPoint(ptCursor.x, ptCursor.y);
                        }
                        catch(System.ComponentModel.Win32Exception)
                        {
                            System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: WindowFromPoint failed!");
                        }

                        if(hwnd != hwndToCheck)
                        {
                            // If we get this far:
                            // - the mouse is NOT over "A"
                            // - "A" does NOT have capture
                            // We consider this a "spurious" mouse move and ignore it. (Win32 bug?)
                            System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: Spurious mouse event received!");
                            return false;
                        }
                    }


                    // We need to collect the current state of the mouse.
                    // Include the activation action.
                    actions |= RawMouseActions.Activate;

                    // Remember that we are active.
                    _active = true;
                    _lastX = x;
                    _lastY = y;

                    //Console.WriteLine("Activating the mouse.");
                }

                // Make sure we are tracking the mouse so we know when it
                // leaves the window.
                StartTracking(hwnd);

                // Even if a move isn't explicitly reported, we still may need to
                // report one if the coordinates are different.  This is to cover
                // some ugly edge cases with context menus and such.
                if((actions & RawMouseActions.AbsoluteMove) == 0)
                {
                    if(x != _lastX || y != _lastY)
                    {
                        actions |= RawMouseActions.AbsoluteMove;
                    }
                }
                else
                {
                    _lastX = x;
                    _lastY = y;
                }

                // record mouse motion so that GetIntermediatePoints has the
                // information it needs
                if ((actions & RawMouseActions.AbsoluteMove) != 0)
                {
                    RecordMouseMove(x, y, _msgTime);
                }

                // MITIGATION: WIN32_AND_AVALON_RTL
                //
                // When a window is marked with the WS_EX_LAYOUTRTL style, Win32
                // mirrors the coordinates received for mouse movement as well as
                // mirroring the output of drawing to a GDI DC.
                //
                // 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 input is already mirrored
                // by Win32, and Avalon mirrors it again.  To work around this
                // problem, we un-mirror the input from Win32 before passing
                // it into Avalon.
                //
                if((actions & (RawMouseActions.AbsoluteMove | RawMouseActions.Activate)) != 0)
                {
                    try
                    {
                        //This has a SUC on it and accesses CriticalHandle
                        int windowStyle = SafeNativeMethods.GetWindowStyle(new HandleRef(this, _source.Value.CriticalHandle), true);

                        if((windowStyle & NativeMethods.WS_EX_LAYOUTRTL) == NativeMethods.WS_EX_LAYOUTRTL)
                        {
                            NativeMethods.RECT rcClient = new NativeMethods.RECT();
                            SafeNativeMethods.GetClientRect(new HandleRef(this,_source.Value.Handle), ref rcClient);
                            x = rcClient.right - x;
                        }
                    }
                    catch(System.ComponentModel.Win32Exception)
                    {
                        System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetWindowStyle or GetClientRect failed!");
                    }
                }
            }


            // Get the extra information sent along with the message.
            //There exists a SUC for this native method call
            IntPtr extraInformation = IntPtr.Zero;
            try
            {
                extraInformation = UnsafeNativeMethods.GetMessageExtraInfo();
            }
            catch(System.ComponentModel.Win32Exception)
            {
                System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetMessageExtraInfo failed!");
            }


            RawMouseInputReport report = new RawMouseInputReport(mode,
                                                                 timestamp,
                                                                 source,
                                                                 actions,
                                                                 x,
                                                                 y,
                                                                 wheel,
                                                                 extraInformation);


            bool handled = _site.Value.ReportInput(report);

            return handled;
        }
Example #24
0
 public static extern IntPtr MonitorFromRect(ref NativeMethods.RECT rect, int flags);
Example #25
0
        // Get bounding rectangle, relative to screen
        internal static Rect GetScreenRect( IntPtr hwnd, UIElement el )
        {            
            Rect rc = GetLocalRect( el );
            
            // Map from local to screen coords...
            NativeMethods.RECT rcWin32 = new NativeMethods.RECT( (int) rc.Left, (int) rc.Top, (int) rc.Right, (int) rc.Bottom );
            try
            {
                SafeSecurityHelper.TransformLocalRectToScreen(new HandleRef(null, hwnd), ref rcWin32);
            }
            catch (System.ComponentModel.Win32Exception)
            {
                return Rect.Empty;
            }

            rc = new Rect( rcWin32.left, rcWin32.top, rcWin32.right - rcWin32.left, rcWin32.bottom - rcWin32.top );

            return rc;
        }
Example #26
0
 public static IntPtr MonitorFromRect(ref NativeMethods.RECT rect, int flags)
 {
     return(SafeNativeMethodsPrivate.MonitorFromRect(ref rect, flags));
 }
        private static void GetClippedPositionOffsets(TextEditor This, ITextPointer position, LogicalDirection direction,
            out double horizontalOffset, out double verticalOffset)
        {
            // GetCharacterRect will return the position that base on UiScope.
            Rect positionRect = position.GetCharacterRect(direction);

            // Get the base offsets for our ContextMenu.
            horizontalOffset = positionRect.X;
            verticalOffset = positionRect.Y + positionRect.Height;

            // Clip to the child render scope.
            FrameworkElement element = This.TextView.RenderScope as FrameworkElement;
            if (element != null)
            {
                GeneralTransform transform = element.TransformToAncestor(This.UiScope);
                if (transform != null)
                {
                    ClipToElement(element, transform, ref horizontalOffset, ref verticalOffset);
                }
            }

            // Clip to parent visuals.
            // This is unintuitive -- you might expect parents to have increasingly
            // larger viewports.  But any parent that behaves like a ScrollViewer
            // will have a smaller view port that we need to clip against.
            for (Visual visual = This.UiScope; visual != null; visual = VisualTreeHelper.GetParent(visual) as Visual)
            {
                element = visual as FrameworkElement;
                if (element != null)
                {
                    GeneralTransform transform = visual.TransformToDescendant(This.UiScope);
                    if (transform != null)
                    {
                        ClipToElement(element, transform, ref horizontalOffset, ref verticalOffset);
                    }
                }
            }

            // Clip to the window client rect.
            PresentationSource source = PresentationSource.CriticalFromVisual(This.UiScope);
            IWin32Window window = source as IWin32Window;
            if (window != null)
            {
                IntPtr hwnd = IntPtr.Zero;
                new UIPermission(UIPermissionWindow.AllWindows).Assert(); // BlessedAssert
                try
                {
                    hwnd = window.Handle;
                }
                finally
                {
                    CodeAccessPermission.RevertAssert();
                }

                NativeMethods.RECT rc = new NativeMethods.RECT(0, 0, 0, 0);
                SafeNativeMethods.GetClientRect(new HandleRef(null, hwnd), ref rc);

                // Convert to mil measure units.
                Point minPoint = new Point(rc.left, rc.top);
                Point maxPoint = new Point(rc.right, rc.bottom);

                CompositionTarget compositionTarget = source.CompositionTarget;
                minPoint = compositionTarget.TransformFromDevice.Transform(minPoint);
                maxPoint = compositionTarget.TransformFromDevice.Transform(maxPoint);

                // Convert to local coordinates.
                GeneralTransform transform = compositionTarget.RootVisual.TransformToDescendant(This.UiScope);
                if (transform != null)
                {
                    transform.TryTransform(minPoint, out minPoint);
                    transform.TryTransform(maxPoint, out maxPoint);

                    // Finally, do the clip.
                    horizontalOffset = ClipToBounds(minPoint.X, horizontalOffset, maxPoint.X);
                    verticalOffset = ClipToBounds(minPoint.Y, verticalOffset, maxPoint.Y);
                }

                // ContextMenu code takes care of clipping to desktop.
            }
        }
        private void HandleBoundingRectChange(IntPtr hwnd)
        {
            NativeMethods.HWND nativeHwnd = NativeMethods.HWND.Cast( hwnd );
            NativeMethods.RECT rc32 = new NativeMethods.RECT(0,0,0,0);

            // if GetWindwRect fails, most likely the nativeHwnd is an invalid window, so just return.
            if (!Misc.GetWindowRect(nativeHwnd, out rc32))
            {
                return;
            }

            // Filter... avoid duplicate events
            if (hwnd == _lastHwnd && Compare( rc32, _lastRect ))
            {
                return;
            }

            AutomationElement rawEl = AutomationElement.FromHandle(hwnd);

            //
            // 





            AutomationPropertyChangedEventArgs e = new AutomationPropertyChangedEventArgs(
                                        AutomationElement.BoundingRectangleProperty, 
                                        Rect.Empty, 
                                        new Rect (rc32.left, rc32.top, rc32.right - rc32.left, rc32.bottom - rc32.top));

            // 





            ClientEventManager.RaiseEventInThisClientOnly(AutomationElement.AutomationPropertyChangedEvent, rawEl, e);

            // save the last hwnd/rect for filtering out duplicates
            _lastHwnd = hwnd;
            _lastRect = rc32;
        }