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