/// <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; }
/// <summary> /// Cache the screen bounds of the monitor in which the targetElement is rendered. /// </summary> /// <param name="itemsPresenter"></param> /// <returns></returns> public static Rect GetScreenBounds(FrameworkElement targetElement, Popup popup) { if (targetElement != null) { Rect targetBoundingBox = new Rect(targetElement.PointToScreen(new Point()), targetElement.PointToScreen(new Point(targetElement.RenderSize.Width, targetElement.RenderSize.Height))); NativeMethods.RECT rect = new NativeMethods.RECT() { top = 0, bottom = 0, left = 0, right = 0 }; NativeMethods.RECT nativeBounds = NativeMethods.FromRect(targetBoundingBox); IntPtr monitor = NativeMethods.MonitorFromRect(ref nativeBounds, NativeMethods.MONITOR_DEFAULTTONEAREST); if (monitor != IntPtr.Zero) { NativeMethods.MONITORINFOEX monitorInfo = new NativeMethods.MONITORINFOEX(); monitorInfo.cbSize = Marshal.SizeOf(typeof(NativeMethods.MONITORINFOEX)); NativeMethods.GetMonitorInfo(new HandleRef(null, monitor), monitorInfo); // WPF Popup special cases MenuItem to be restricted to work area // Hence Ribbon applies the same rules as well. if (popup.TemplatedParent is RibbonMenuItem) { rect = monitorInfo.rcWork; } else if (popup.TemplatedParent is RibbonMenuButton) { rect = monitorInfo.rcMonitor; } } return NativeMethods.ToRect(rect); } return Rect.Empty; }