/// <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; } } }