WindowResizer.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Windows;
  6. using System.Windows.Input;
  7. using System.Windows.Interop;
  8. using System.Windows.Media;
  9. namespace Muchinfo.WPF.Controls.Windows
  10. {
  11. public class WindowResizer
  12. {
  13. /// <summary>
  14. /// Defines the cursors that should be used when the mouse is hovering
  15. /// over a border in each position.
  16. /// </summary>
  17. private readonly Dictionary<BorderPosition, Cursor> cursors = new Dictionary<BorderPosition, Cursor>
  18. {
  19. { BorderPosition.Left, Cursors.SizeWE },
  20. { BorderPosition.Right, Cursors.SizeWE },
  21. { BorderPosition.Top, Cursors.SizeNS },
  22. { BorderPosition.Bottom, Cursors.SizeNS },
  23. { BorderPosition.BottomLeft, Cursors.SizeNESW },
  24. { BorderPosition.TopRight, Cursors.SizeNESW },
  25. { BorderPosition.BottomRight, Cursors.SizeNWSE },
  26. { BorderPosition.TopLeft, Cursors.SizeNWSE }
  27. };
  28. /// <summary>
  29. /// The borders for the window.
  30. /// </summary>
  31. private readonly WindowBorder[] _borders;
  32. /// <summary>
  33. /// The handle to the window.
  34. /// </summary>
  35. private HwndSource _hwndSource;
  36. /// <summary>
  37. /// The WPF window.
  38. /// </summary>
  39. private readonly Window _window;
  40. /// <summary>
  41. /// Creates a new WindowResizer for the specified Window using the
  42. /// specified border elements.
  43. /// </summary>
  44. /// <param name="window">The Window which should be resized.</param>
  45. /// <param name="borders">The elements which can be used to resize the window.</param>
  46. public WindowResizer(Window window, params WindowBorder[] borders)
  47. {
  48. if (window == null)
  49. {
  50. throw new ArgumentNullException("window");
  51. }
  52. if (borders == null)
  53. {
  54. throw new ArgumentNullException("borders");
  55. }
  56. this._window = window;
  57. this._borders = borders;
  58. foreach (var border in borders)
  59. {
  60. border.Element.PreviewMouseLeftButtonDown += Resize;
  61. border.Element.MouseMove += DisplayResizeCursor;
  62. border.Element.MouseLeave += ResetCursor;
  63. }
  64. window.SourceInitialized += (o, e) => _hwndSource = (HwndSource)PresentationSource.FromVisual((Visual)o);
  65. }
  66. /// <summary>
  67. /// Sticks a message on the message queue.
  68. /// </summary>
  69. /// <param name="hWnd"></param>
  70. /// <param name="Msg"></param>
  71. /// <param name="wParam"></param>
  72. /// <param name="lParam"></param>
  73. /// <returns></returns>
  74. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  75. private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
  76. /// <summary>
  77. /// Puts a resize message on the message queue for the specified border position.
  78. /// </summary>
  79. /// <param name="direction"></param>
  80. private void ResizeWindow(BorderPosition direction)
  81. {
  82. SendMessage(_hwndSource.Handle, 0x112, (IntPtr)direction, IntPtr.Zero);
  83. }
  84. /// <summary>
  85. /// Resets the cursor when the left mouse button is not pressed.
  86. /// </summary>
  87. /// <param name="sender"></param>
  88. /// <param name="e"></param>
  89. private void ResetCursor(object sender, MouseEventArgs e)
  90. {
  91. if (Mouse.LeftButton != MouseButtonState.Pressed)
  92. {
  93. _window.Cursor = Cursors.Arrow;
  94. }
  95. }
  96. /// <summary>
  97. /// Resizes the window.
  98. /// </summary>
  99. /// <param name="sender"></param>
  100. /// <param name="e"></param>
  101. private void Resize(object sender, MouseButtonEventArgs e)
  102. {
  103. var border = _borders.Single(b => b.Element.Equals(sender));
  104. _window.Cursor = cursors[border.Position];
  105. ResizeWindow(border.Position);
  106. }
  107. /// <summary>
  108. /// Ensures that the correct cursor is displayed.
  109. /// </summary>
  110. /// <param name="sender"></param>
  111. /// <param name="e"></param>
  112. private void DisplayResizeCursor(object sender, MouseEventArgs e)
  113. {
  114. var border = _borders.Single(b => b.Element.Equals(sender));
  115. _window.Cursor = cursors[border.Position];
  116. }
  117. }
  118. }