/// <summary>
 /// Get the WindowState as the native HWND knows it to be.  This isn't necessarily the same as what Window thinks.
 /// </summary>
 private WindowState GetHwndState()
 {
     NativeMethods.WINDOWPLACEMENT wpl = new NativeMethods.WINDOWPLACEMENT();
     NativeMethods.GetWindowPlacement(handle, wpl);
     switch (wpl.showCmd)
     {
         case NativeMethods.SW_SHOWMINIMIZED: return WindowState.Minimized;
         case NativeMethods.SW_SHOWMAXIMIZED: return WindowState.Maximized;
     }
     return WindowState.Normal;
 }
        private void SetRoundingRegion(NativeMethods.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.
            NativeMethods.WINDOWPLACEMENT wpl = new NativeMethods.WINDOWPLACEMENT();
            NativeMethods.GetWindowPlacement(handle, wpl);

            if (wpl.showCmd == NativeMethods.SW_SHOWMAXIMIZED && IsDwmEnabled == true)
            {
                int left;
                int top;

                if (wp.HasValue)
                {
                    left = wp.Value.x;
                    top = wp.Value.y;
                }
                else
                {
                    NativeMethods.Rect r = new NativeMethods.Rect();
                    NativeMethods.GetWindowRect(handle, ref r);
                    left = r.Left;
                    top = r.Top;
                }

                IntPtr hMon = NativeMethods.MonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST);

                NativeMethods.MonitorInfo mi = new NativeMethods.MonitorInfo();
                NativeMethods.GetMonitorInfo(hMon, mi);
                NativeMethods.Rect rcMax = mi.Work;
                // The location of maximized window takes into account the border that Windows was
                // going to remove, so we also need to consider it.
                rcMax.Left -= left; rcMax.Right -= left;
                rcMax.Top -= top; rcMax.Bottom -= top;

                IntPtr hrgn = IntPtr.Zero;
                try
                {
                    hrgn = NativeMethods.CreateRectRgnIndirect(ref rcMax);
                    NativeMethods.SetWindowRgn(handle, hrgn, NativeMethods.IsWindowVisible(handle));
                    hrgn = IntPtr.Zero;
                }
                finally
                {
                    NativeMethods.DeleteObject(hrgn);
                }
            }
            else
            {
                Size windowSize;

                // Use the size if it's specified.
                if (null != wp && !IsFlagSet(wp.Value.flags, NativeMethods.SWP_NOSIZE))
                {
                    windowSize = new Size((double)wp.Value.cx, (double)wp.Value.cy);
                }
                else if (null != wp && (lastRoundingState == WindowState))
                {
                    return;
                }
                else
                {
                    NativeMethods.Rect r = new NativeMethods.Rect();
                    NativeMethods.GetWindowRect(handle, ref r);
                    Rect rect = new Rect(r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top);
                    windowSize = rect.Size;
                }

                lastRoundingState = WindowState;

                IntPtr hrgn = IntPtr.Zero;
                try
                {
                    double shortestDimension = Math.Min(windowSize.Width, windowSize.Height);

                    double topLeftRadius = DpiHelper.LogicalPixelsToDevice(new Point(CornerRadius.TopLeft, 0)).X;
                    topLeftRadius = Math.Min(topLeftRadius, shortestDimension / 2);

                    if (IsUniform(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(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);

                        CreateAndCombineRoundRectRgn(hrgn, topRightRegionRect, topRightRadius);

                        double bottomLeftRadius = /*DpiHelper.LogicalPixelsToDevice*/(new Point(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);

                        CreateAndCombineRoundRectRgn(hrgn, bottomLeftRegionRect, bottomLeftRadius);

                        double bottomRightRadius = DpiHelper.LogicalPixelsToDevice(new Point(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);

                        CreateAndCombineRoundRectRgn(hrgn, bottomRightRegionRect, bottomRightRadius);
                    }

                    NativeMethods.SetWindowRgn(handle, hrgn, NativeMethods.IsWindowVisible(handle));
                    hrgn = IntPtr.Zero;
                }
                finally
                {
                    // Free the memory associated with the HRGN if it wasn't assigned to the HWND.
                    NativeMethods.DeleteObject(hrgn);
                }
            }
        }
        private void FixRestoreBounds(object sender, EventArgs e)
        {
            if (WindowState == WindowState.Maximized || WindowState == WindowState.Minimized)
            {
                // Old versions of WPF sometimes force their incorrect idea of the Window's location
                // on the Win32 restore bounds.  If we have reason to think this is the case, then
                // try to undo what WPF did after it has done its thing.
                if (hasUserMovedWindow)
                {
                    hasUserMovedWindow = false;
                    NativeMethods.WINDOWPLACEMENT wp = new NativeMethods.WINDOWPLACEMENT();
                    NativeMethods.GetWindowPlacement(handle, wp);

                    NativeMethods.Rect adjustedDeviceRc = GetAdjustedWindowRect(new NativeMethods.Rect { Bottom = 100, Right = 100 });
                    Point adjustedTopLeft = DpiHelper.DevicePixelsToLogical(
                        new Point(
                            wp.rcNormalPosition.Left - adjustedDeviceRc.Left,
                            wp.rcNormalPosition.Top - adjustedDeviceRc.Top));

                    Top = adjustedTopLeft.Y;
                    Left = adjustedTopLeft.X;
                }
            }
        }