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);
                }
            }
        }
Example #3
0
      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));
         }
      }