Files
mpv.net/src/WinForms/SnapManager.cs

82 lines
2.9 KiB
C#

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using static mpvnet.Native;
namespace mpvnet
{
public class SnapManager
{
int DragOffsetX { get; set; }
int DragOffsetY { get; set; }
IntPtr Handle;
[Flags]
public enum SnapLocation
{
None = 0,
Left = 1 << 0,
Top = 1 << 1,
Right = 1 << 2,
Bottom = 1 << 3,
All = Left | Top | Right | Bottom
}
public int AnchorDistance { get; set; }
public int SnapDistance { get; set; }
bool InSnapRange(int a, int b) => Math.Abs(a - b) < SnapDistance;
void FindSnap(ref Rectangle effectiveBounds)
{
Screen currentScreen = Screen.FromPoint(effectiveBounds.Location);
Rectangle workingArea = GetWorkingArea(Handle, currentScreen.WorkingArea);
if (InSnapRange(effectiveBounds.Left, workingArea.Left + AnchorDistance))
effectiveBounds.X = workingArea.Left + AnchorDistance;
else if (InSnapRange(effectiveBounds.Right, workingArea.Right - AnchorDistance))
effectiveBounds.X = workingArea.Right - AnchorDistance - effectiveBounds.Width;
if (InSnapRange(effectiveBounds.Top, workingArea.Top + AnchorDistance))
effectiveBounds.Y = workingArea.Top + AnchorDistance;
else if (InSnapRange(effectiveBounds.Bottom, workingArea.Bottom - AnchorDistance))
effectiveBounds.Y = workingArea.Bottom - AnchorDistance - effectiveBounds.Height;
}
public void OnMoving(ref Message m)
{
if (Handle == IntPtr.Zero)
return;
RECT boundsLtrb = Marshal.PtrToStructure<RECT>(m.LParam);
Rectangle bounds = boundsLtrb.ToRectangle();
// This is where the window _would_ be located if snapping
// had not occurred. This prevents the cursor from sliding
// off the title bar if the snap distance is too large.
Rectangle effectiveBounds = new Rectangle(
Cursor.Position.X - DragOffsetX,
Cursor.Position.Y - DragOffsetY,
bounds.Width,
bounds.Height);
FindSnap(ref effectiveBounds);
RECT newLtrb = RECT.FromRectangle(effectiveBounds);
Marshal.StructureToPtr(newLtrb, m.LParam, false);
m.Result = new IntPtr(1);
}
public void OnSizeAndEnterSizeMove(Form form)
{
Handle = form.Handle;
SnapDistance = form.Font.Height;
// Need to handle window size changed as well when
// un-maximizing the form by dragging the title bar.
DragOffsetX = Cursor.Position.X - form.Left;
DragOffsetY = Cursor.Position.Y - form.Top;
}
}
}