private IntPtr _HandleWindowPosChanged(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) { // http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx // The WM_WINDOWPOSCHANGED message is sent at the end of the window // state change process. It sort of combines the other state change // notifications, WM_MOVE, WM_SIZE, and WM_SHOWWINDOW. But it doesn't // suffer from the same limitations as WM_SHOWWINDOW, so you can // reliably use it to react to the window being shown or hidden. _UpdateSystemMenu(null); if (!_isGlassEnabled) { Assert.IsNotDefault(lParam); var wp = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS)); if (!wp.Equals(_previousWP)) { _previousWP = wp; _SetRoundingRegion(wp); } // if (wp.Equals(_previousWP) && wp.flags.Equals(_previousWP.flags)) // { // handled = true; // return IntPtr.Zero; // } _previousWP = wp; } // Still want to pass this to DefWndProc handled = false; return IntPtr.Zero; }
private void _SetRoundingRegion(WINDOWPOS? wp) { const int MONITOR_DEFAULTTONEAREST = 0x00000002; // We're early - WPF hasn't necessarily updated the state of the window. // Need to query it ourselves. WINDOWPLACEMENT wpl = NativeMethods.GetWindowPlacement(_hwnd); if (wpl.showCmd == SW.SHOWMAXIMIZED) { int left; int top; if (wp.HasValue) { left = wp.Value.x; top = wp.Value.y; } else { Rect r = _GetWindowRect(); left = (int)r.Left; top = (int)r.Top; } IntPtr hMon = NativeMethods.MonitorFromWindow(_hwnd, MONITOR_DEFAULTTONEAREST); MONITORINFO mi = NativeMethods.GetMonitorInfo(hMon); RECT rcMax = mi.rcWork; // The location of maximized window takes into account the border that Windows was // going to remove, so we also need to consider it. rcMax.Offset(-left, -top); IntPtr hrgn = IntPtr.Zero; try { hrgn = NativeMethods.CreateRectRgnIndirect(rcMax); NativeMethods.SetWindowRgn(_hwnd, hrgn, NativeMethods.IsWindowVisible(_hwnd)); hrgn = IntPtr.Zero; } finally { Utility.SafeDeleteObject(ref hrgn); } } else { Size windowSize; // Use the size if it's specified. if (null != wp && !Utility.IsFlagSet(wp.Value.flags, (int)SWP.NOSIZE)) { windowSize = new Size((double)wp.Value.cx, (double)wp.Value.cy); } else if (null != wp && (_lastRoundingState == _window.WindowState)) { return; } else { windowSize = _GetWindowRect().Size; } _lastRoundingState = _window.WindowState; IntPtr hrgn = IntPtr.Zero; try { double shortestDimension = Math.Min(windowSize.Width, windowSize.Height); double topLeftRadius = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.CornerRadius.TopLeft, 0)).X; topLeftRadius = Math.Min(topLeftRadius, shortestDimension / 2); if (_IsUniform(_chromeInfo.CornerRadius)) { // RoundedRect HRGNs require an additional pixel of padding. hrgn = _CreateRoundRectRgn(new Rect(windowSize), topLeftRadius); } else { // We need to combine HRGNs for each of the corners. // Create one for each quadrant, but let it overlap into the two adjacent ones // by the radius amount to ensure that there aren't corners etched into the middle // of the window. hrgn = _CreateRoundRectRgn(new Rect(0, 0, windowSize.Width / 2 + topLeftRadius, windowSize.Height / 2 + topLeftRadius), topLeftRadius); double topRightRadius = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.CornerRadius.TopRight, 0)).X; topRightRadius = Math.Min(topRightRadius, shortestDimension / 2); Rect topRightRegionRect = new Rect(0, 0, windowSize.Width / 2 + topRightRadius, windowSize.Height / 2 + topRightRadius); topRightRegionRect.Offset(windowSize.Width / 2 - topRightRadius, 0); Assert.AreEqual(topRightRegionRect.Right, windowSize.Width); _CreateAndCombineRoundRectRgn(hrgn, topRightRegionRect, topRightRadius); double bottomLeftRadius = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.CornerRadius.BottomLeft, 0)).X; bottomLeftRadius = Math.Min(bottomLeftRadius, shortestDimension / 2); Rect bottomLeftRegionRect = new Rect(0, 0, windowSize.Width / 2 + bottomLeftRadius, windowSize.Height / 2 + bottomLeftRadius); bottomLeftRegionRect.Offset(0, windowSize.Height / 2 - bottomLeftRadius); Assert.AreEqual(bottomLeftRegionRect.Bottom, windowSize.Height); _CreateAndCombineRoundRectRgn(hrgn, bottomLeftRegionRect, bottomLeftRadius); double bottomRightRadius = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.CornerRadius.BottomRight, 0)).X; bottomRightRadius = Math.Min(bottomRightRadius, shortestDimension / 2); Rect bottomRightRegionRect = new Rect(0, 0, windowSize.Width / 2 + bottomRightRadius, windowSize.Height / 2 + bottomRightRadius); bottomRightRegionRect.Offset(windowSize.Width / 2 - bottomRightRadius, windowSize.Height / 2 - bottomRightRadius); Assert.AreEqual(bottomRightRegionRect.Right, windowSize.Width); Assert.AreEqual(bottomRightRegionRect.Bottom, windowSize.Height); _CreateAndCombineRoundRectRgn(hrgn, bottomRightRegionRect, bottomRightRadius); } NativeMethods.SetWindowRgn(_hwnd, hrgn, NativeMethods.IsWindowVisible(_hwnd)); hrgn = IntPtr.Zero; } finally { // Free the memory associated with the HRGN if it wasn't assigned to the HWND. Utility.SafeDeleteObject(ref hrgn); } } }
private void _SetRoundingRegion(WINDOWPOS? wp) { const int MONITOR_DEFAULTTONEAREST = 0x00000002; // We're early - WPF hasn't necessarily updated the state of the window. // Need to query it ourselves. WINDOWPLACEMENT wpl = NativeMethods.GetWindowPlacement(_hwnd); if (wpl.showCmd == SW.SHOWMAXIMIZED) { int left; int top; if (wp.HasValue) { left = wp.Value.x; top = wp.Value.y; } else { Rect r = _GetWindowRect(); left = (int)r.Left; top = (int)r.Top; } IntPtr hMon = NativeMethods.MonitorFromWindow(_hwnd, MONITOR_DEFAULTTONEAREST); MONITORINFO mi = NativeMethods.GetMonitorInfo(hMon); RECT rcMax = mi.rcWork; // The location of maximized window takes into account the border that Windows was // going to remove, so we also need to consider it. rcMax.Offset(-left, -top); IntPtr hrgn = NativeMethods.CreateRectRgnIndirect(rcMax); NativeMethods.SetWindowRgn(_hwnd, hrgn, NativeMethods.IsWindowVisible(_hwnd)); } else { int width; int height; // Use the size if it's specified. if (null != wp && !Utility.IsFlagSet(wp.Value.flags, (int)SWP.NOSIZE)) { width = wp.Value.cx; height = wp.Value.cy; } else if (null != wp && (_lastRoundingState == _window.WindowState)) { return; } else { Rect r = _GetWindowRect(); width = (int)r.Width; height = (int)r.Height; } _lastRoundingState = _window.WindowState; IntPtr hrgn = IntPtr.Zero; //var maxCorner = Math.Max( // Math.Max(CornerRadius.BottomLeft, CornerRadius.BottomRight), // Math.Max(CornerRadius.TopLeft, CornerRadius.TopRight)); //if (maxCorner > 0) // { // Point radius = DpiHelper.LogicalPixelsToDevice(new Point(maxCorner, maxCorner)); // hrgn = NativeMethods.CreateRoundRectRgn(0, 0, width, height, (int)radius.X * 2, (int)radius.Y * 2); // radius = DpiHelper.LogicalPixelsToDevice(new Point(CornerRadius.TopLeft, CornerRadius.TopLeft)); // IntPtr corner = NativeMethods.CreateRoundRectRgn(0, 0, width / 2, height / 2, (int)radius.X * 2, (int)radius.Y * 2); // hrgn = NativeMethods.OrRgn(hrgn, corner); // radius = DpiHelper.LogicalPixelsToDevice(new Point(CornerRadius.TopRight, CornerRadius.TopRight)); // corner = NativeMethods.CreateRoundRectRgn(width / 2, 0, width, height / 2, (int)radius.X * 2, (int)radius.Y * 2); // hrgn = NativeMethods.OrRgn(hrgn, corner); // radius = DpiHelper.LogicalPixelsToDevice(new Point(CornerRadius.BottomLeft, CornerRadius.BottomLeft)); // corner = NativeMethods.CreateRoundRectRgn(0, height / 2, width / 2, height, (int)radius.X * 2, (int)radius.Y * 2); // hrgn = NativeMethods.OrRgn(hrgn, corner); // radius = DpiHelper.LogicalPixelsToDevice(new Point(CornerRadius.BottomRight, CornerRadius.BottomRight)); // corner = NativeMethods.CreateRoundRectRgn(width / 2, height / 2, width, height, (int)radius.X * 2, (int)radius.Y * 2); // hrgn = NativeMethods.OrRgn(hrgn, corner); //} // else // { hrgn = NativeMethods.CreateRectRgn(0, 0, width, height); //} _window.Background = _background; NativeMethods.SetWindowRgn(_hwnd, hrgn, NativeMethods.IsWindowVisible(_hwnd)); } }