JD2022-TU1/main/tools/framework/JD.WPF/Utils/WindowResizer.cs

329 lines
7.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Input;
namespace JD.WPF.Utils
{
public class WindowResizer
{
private readonly Window _target;
private bool _resizeRight;
private bool _resizeLeft;
private bool _resizeUp;
private bool _resizeDown;
private readonly Dictionary<UIElement, short> _leftElements = new Dictionary<UIElement, short>();
private readonly Dictionary<UIElement, short> _rightElements = new Dictionary<UIElement, short>();
private readonly Dictionary<UIElement, short> _upElements = new Dictionary<UIElement, short>();
private readonly Dictionary<UIElement, short> _downElements = new Dictionary<UIElement, short>();
private PointAPI _resizePoint;
private Size _resizeSize;
private Point _resizeWindowPoint;
private delegate void RefreshDelegate();
public WindowResizer(Window target)
{
_target = target;
if (target == null)
{
throw new Exception("Invalid Window handle");
}
}
private void ConnectMouseHandlers(UIElement element)
{
if ( element == null )
return;
element.MouseLeftButtonDown += Element_MouseLeftButtonDown;
element.MouseLeftButtonUp += Element_MouseLeftButtonUp;
element.MouseEnter += Element_MouseEnter;
element.MouseLeave += SetArrowCursor;
}
public void AddResizerRight(UIElement element)
{
if ( element == null )
return;
ConnectMouseHandlers(element);
_rightElements.Add(element, 0);
}
public void AddResizerLeft(UIElement element)
{
if ( element == null )
return;
ConnectMouseHandlers(element);
_leftElements.Add(element, 0);
}
public void AddResizerUp(UIElement element)
{
if ( element == null )
return;
ConnectMouseHandlers(element);
_upElements.Add(element, 0);
}
public void AddResizerDown(UIElement element)
{
if ( element == null )
return;
ConnectMouseHandlers(element);
_downElements.Add(element, 0);
}
public void AddResizerRightDown(UIElement element)
{
if ( element == null )
return;
ConnectMouseHandlers(element);
_rightElements.Add(element, 0);
_downElements.Add(element, 0);
}
public void AddResizerLeftDown(UIElement element)
{
if ( element == null )
return;
ConnectMouseHandlers(element);
_leftElements.Add(element, 0);
_downElements.Add(element, 0);
}
public void AddResizerRightUp(UIElement element)
{
if ( element == null )
return;
ConnectMouseHandlers(element);
_rightElements.Add(element, 0);
_upElements.Add(element, 0);
}
public void AddResizerLeftUp(UIElement element)
{
if ( element == null )
return;
ConnectMouseHandlers(element);
_leftElements.Add(element, 0);
_upElements.Add(element, 0);
}
private void Element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if ((sender as UIElement).Visibility != Visibility.Visible)
return;
(sender as UIElement)?.CaptureMouse();
GetCursorPos(out _resizePoint);
_resizeSize = new Size(_target.Width, _target.Height);
_resizeWindowPoint = new Point(_target.Left, _target.Top);
UIElement sourceSender = (UIElement)sender;
if (_leftElements.ContainsKey(sourceSender))
{
_resizeLeft = true;
}
if (_rightElements.ContainsKey(sourceSender))
{
_resizeRight = true;
}
if (_upElements.ContainsKey(sourceSender))
{
_resizeUp = true;
}
if (_downElements.ContainsKey(sourceSender))
{
_resizeDown = true;
}
Thread t = new Thread(UpdateSizeLoop) {Name = "Mouse Position Poll Thread"};
t.Start();
}
void Element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
(sender as UIElement).ReleaseMouseCapture();
}
private void UpdateSizeLoop()
{
try
{
while (_resizeDown || _resizeLeft || _resizeRight || _resizeUp)
{
_target.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new RefreshDelegate(UpdateSize));
_target.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new RefreshDelegate(UpdateMouseDown));
Thread.Sleep(10);
}
_target.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new RefreshDelegate(SetArrowCursor));
}
catch (Exception)
{
// continue
}
}
private void UpdateSize()
{
PointAPI p;
GetCursorPos(out p);
if (_resizeRight)
{
_target.Width = Math.Max(_target.MinWidth, _resizeSize.Width - (_resizePoint.X - p.X));
}
if (_resizeDown)
{
_target.Height = Math.Max(_target.MinHeight, _resizeSize.Height - (_resizePoint.Y - p.Y));
}
if (_resizeLeft)
{
// TODO : Fix refresh issues.
double currentRight = _target.Left + _target.Width;
double candidateLeft = _resizeWindowPoint.X - (_resizePoint.X - p.X);
if (candidateLeft + _target.MinWidth > currentRight)
_target.Left = currentRight - _target.MinWidth;
else
_target.Left = candidateLeft;
_target.Width = Math.Max(_target.MinWidth, _resizeSize.Width + (_resizePoint.X - p.X));
}
if (_resizeUp)
{
// TODO : Fix Refresh issues.
double currentBottom = _target.Top + _target.Height;
double candidateTop = _resizeWindowPoint.Y - (_resizePoint.Y - p.Y);
if (candidateTop + _target.MinHeight > currentBottom)
_target.Top = currentBottom - _target.MinHeight;
else
_target.Top = candidateTop;
_target.Height = Math.Max(_target.MinHeight, _resizeSize.Height + (_resizePoint.Y - p.Y));
}
}
private void UpdateMouseDown()
{
if (Mouse.LeftButton == MouseButtonState.Released)
{
_resizeRight = false;
_resizeLeft = false;
_resizeUp = false;
_resizeDown = false;
}
}
private void Element_MouseEnter(object sender, MouseEventArgs e)
{
bool resizeRight = false;
bool resizeLeft = false;
bool resizeUp = false;
bool resizeDown = false;
var window = (Window)((FrameworkElement)sender).TemplatedParent;
if ( window != null && window.WindowState == WindowState.Maximized)
{
return;
}
UIElement sourceSender = (UIElement)sender;
if (_leftElements.ContainsKey(sourceSender))
{
resizeLeft = true;
}
if (_rightElements.ContainsKey(sourceSender))
{
resizeRight = true;
}
if (_upElements.ContainsKey(sourceSender))
{
resizeUp = true;
}
if (_downElements.ContainsKey(sourceSender))
{
resizeDown = true;
}
if ((resizeLeft && resizeDown) || (resizeRight && resizeUp))
{
SetNESWCursor(sender, e);
}
else if ((resizeRight && resizeDown) || (resizeLeft && resizeUp))
{
SetNWSECursor(sender, e);
}
else if (resizeLeft || resizeRight)
{
SetWECursor(sender, e);
}
else if (resizeUp || resizeDown)
{
SetNSCursor(sender, e);
}
}
private void SetWECursor(object sender, MouseEventArgs e)
{
_target.Cursor = Cursors.SizeWE;
}
private void SetNSCursor(object sender, MouseEventArgs e)
{
_target.Cursor = Cursors.SizeNS;
}
private void SetNESWCursor(object sender, MouseEventArgs e)
{
_target.Cursor = Cursors.SizeNESW;
}
private void SetNWSECursor(object sender, MouseEventArgs e)
{
_target.Cursor = Cursors.SizeNWSE;
}
private void SetArrowCursor(object sender, MouseEventArgs e)
{
if (!_resizeDown && !_resizeLeft && !_resizeRight && !_resizeUp)
{
_target.Cursor = Cursors.Arrow;
}
}
private void SetArrowCursor()
{
_target.Cursor = Cursors.Arrow;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(out PointAPI lpPoint);
private struct PointAPI
{
public int X;
public int Y;
}
}
}