#region Imports using DPumpHydr.WinFrmUI.RLT.Docking.Crown; using DPumpHydr.WinFrmUI.RLT.Enum.Crown; using System; using System.Drawing; using System.Windows.Forms; #endregion namespace DPumpHydr.WinFrmUI.RLT.Native { #region DockResizeFilterNative public class DockResizeFilter : IMessageFilter { #region Field Region private readonly CrownDockPanel _dockPanel; private readonly Timer _dragTimer; private bool _isDragging; private Point _initialContact; private CrownDockSplitter _activeSplitter; #endregion #region Constructor Region public DockResizeFilter(CrownDockPanel dockPanel) { _dockPanel = dockPanel; _dragTimer = new Timer { Interval = 1 }; _dragTimer.Tick += DragTimer_Tick; } #endregion #region IMessageFilter Region public bool PreFilterMessage(ref Message m) { // We only care about mouse events if (m.Msg is not (((int)WM.MOUSEMOVE) or ((int)WM.LBUTTONDOWN) or ((int)WM.LBUTTONUP) or ((int)WM.LBUTTONDBLCLK) or ((int)WM.RBUTTONDOWN) or ((int)WM.RBUTTONUP) or ((int)WM.RBUTTONDBLCLK))) { return false; } // Stop drag. if (m.Msg == (int)WM.LBUTTONUP) { if (_isDragging) { StopDrag(); return true; } } // Exit out early if we're simply releasing a non-splitter drag over the area if (m.Msg == (int)WM.LBUTTONUP && !_isDragging) { return false; } // Force cursor if already dragging. if (_isDragging) { Cursor.Current = _activeSplitter.ResizeCursor; } // Return out early if we're dragging something that's not a splitter. if (m.Msg == (int)WM.MOUSEMOVE && !_isDragging && _dockPanel.MouseButtonState != MouseButtons.None) { return false; } // Try and create a control from the message handle. Control control = Control.FromHandle(m.HWnd); // Exit out if we didn't manage to create a control. if (control == null) { return false; } // Exit out if the control is not the dock panel or a child control. if (!(control == _dockPanel || _dockPanel.Contains(control))) { return false; } // Update the mouse cursor CheckCursor(); // Start drag. if (m.Msg == (int)WM.LBUTTONDOWN) { CrownDockSplitter hotSplitter = HotSplitter(); if (hotSplitter != null) { StartDrag(hotSplitter); return true; } } // Stop events passing through if we're hovering over a splitter if (HotSplitter() != null) { return true; } // Stop all events from going through if we're dragging a splitter. if (_isDragging) { return true; } return false; } #endregion #region Event Handler Region private void DragTimer_Tick(object sender, EventArgs e) { if (_dockPanel.MouseButtonState != MouseButtons.Left) { StopDrag(); return; } Point difference = new(_initialContact.X - Cursor.Position.X, _initialContact.Y - Cursor.Position.Y); _activeSplitter.UpdateOverlay(difference); } #endregion #region Method Region private void StartDrag(CrownDockSplitter splitter) { _activeSplitter = splitter; Cursor.Current = _activeSplitter.ResizeCursor; _initialContact = Cursor.Position; _isDragging = true; _activeSplitter.ShowOverlay(); _dragTimer.Start(); } private void StopDrag() { _dragTimer.Stop(); _activeSplitter.HideOverlay(); Point difference = new(_initialContact.X - Cursor.Position.X, _initialContact.Y - Cursor.Position.Y); _activeSplitter.Move(difference); _isDragging = false; } private CrownDockSplitter HotSplitter() { foreach (CrownDockSplitter splitter in _dockPanel.Splitters) { if (splitter.Bounds.Contains(Cursor.Position)) { return splitter; } } return null; } private void CheckCursor() { if (_isDragging) { return; } CrownDockSplitter hotSplitter = HotSplitter(); if (hotSplitter != null) { Cursor.Current = hotSplitter.ResizeCursor; } } private void ResetCursor() { Cursor.Current = Cursors.Default; CheckCursor(); } #endregion } #endregion }