using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; namespace Muchinfo.WPF.Controls.Windows { public class WindowResizer { /// /// Defines the cursors that should be used when the mouse is hovering /// over a border in each position. /// private readonly Dictionary cursors = new Dictionary { { BorderPosition.Left, Cursors.SizeWE }, { BorderPosition.Right, Cursors.SizeWE }, { BorderPosition.Top, Cursors.SizeNS }, { BorderPosition.Bottom, Cursors.SizeNS }, { BorderPosition.BottomLeft, Cursors.SizeNESW }, { BorderPosition.TopRight, Cursors.SizeNESW }, { BorderPosition.BottomRight, Cursors.SizeNWSE }, { BorderPosition.TopLeft, Cursors.SizeNWSE } }; /// /// The borders for the window. /// private readonly WindowBorder[] _borders; /// /// The handle to the window. /// private HwndSource _hwndSource; /// /// The WPF window. /// private readonly Window _window; /// /// Creates a new WindowResizer for the specified Window using the /// specified border elements. /// /// The Window which should be resized. /// The elements which can be used to resize the window. public WindowResizer(Window window, params WindowBorder[] borders) { if (window == null) { throw new ArgumentNullException("window"); } if (borders == null) { throw new ArgumentNullException("borders"); } this._window = window; this._borders = borders; foreach (var border in borders) { border.Element.PreviewMouseLeftButtonDown += Resize; border.Element.MouseMove += DisplayResizeCursor; border.Element.MouseLeave += ResetCursor; } window.SourceInitialized += (o, e) => _hwndSource = (HwndSource)PresentationSource.FromVisual((Visual)o); } /// /// Sticks a message on the message queue. /// /// /// /// /// /// [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); /// /// Puts a resize message on the message queue for the specified border position. /// /// private void ResizeWindow(BorderPosition direction) { SendMessage(_hwndSource.Handle, 0x112, (IntPtr)direction, IntPtr.Zero); } /// /// Resets the cursor when the left mouse button is not pressed. /// /// /// private void ResetCursor(object sender, MouseEventArgs e) { if (Mouse.LeftButton != MouseButtonState.Pressed) { _window.Cursor = Cursors.Arrow; } } /// /// Resizes the window. /// /// /// private void Resize(object sender, MouseButtonEventArgs e) { var border = _borders.Single(b => b.Element.Equals(sender)); _window.Cursor = cursors[border.Position]; ResizeWindow(border.Position); } /// /// Ensures that the correct cursor is displayed. /// /// /// private void DisplayResizeCursor(object sender, MouseEventArgs e) { var border = _borders.Single(b => b.Element.Equals(sender)); _window.Cursor = cursors[border.Position]; } } }