| File: System\Windows\Forms\Controls\ToolStrips\ToolStripGrip.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms\System.Windows.Forms.csproj (System.Windows.Forms) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Drawing; using System.Windows.Forms.Layout; namespace System.Windows.Forms; internal partial class ToolStripGrip : ToolStripButton { private Cursor? _oldCursor; private Point _startLocation = Point.Empty; private bool _movingToolStrip; private Point _lastEndLocation = ToolStrip.s_invalidMouseEnter; private static Size s_dragSize = LayoutUtils.s_maxSize; private Padding _defaultPadding; internal ToolStripGrip() { ScaleConstants(ScaleHelper.InitialSystemDpi); SupportsItemClick = false; } protected internal override Padding DefaultMargin => _defaultPadding; public override bool CanSelect => false; internal int GripThickness { get; private set; } [MemberNotNullWhen(true, nameof(ToolStripPanelRow))] internal bool MovingToolStrip { get => (ToolStripPanelRow is not null) && _movingToolStrip; set { if ((_movingToolStrip != value) && ParentInternal is not null) { if (value) { // don't let grips move the toolstrip if (ParentInternal.ToolStripPanelRow is null) { return; } } _movingToolStrip = value; _lastEndLocation = ToolStrip.s_invalidMouseEnter; if (_movingToolStrip) { ((ISupportToolStripPanel)ParentInternal).BeginDrag(); } else { ((ISupportToolStripPanel)ParentInternal).EndDrag(); } } } } private ToolStripPanelRow? ToolStripPanelRow { get { return (ParentInternal is null) ? null : ((ISupportToolStripPanel)ParentInternal).ToolStripPanelRow; } } protected override AccessibleObject CreateAccessibilityInstance() { return new ToolStripGripAccessibleObject(this); } public override Size GetPreferredSize(Size constrainingSize) { Size preferredSize = Size.Empty; if (ParentInternal is not null) { if (ParentInternal.LayoutStyle == ToolStripLayoutStyle.VerticalStackWithOverflow) { preferredSize = new Size(ParentInternal.Width, GripThickness); } else { preferredSize = new Size(GripThickness, ParentInternal.Height); } } // Constrain ourselves if (preferredSize.Width > constrainingSize.Width) { preferredSize.Width = constrainingSize.Width; } if (preferredSize.Height > constrainingSize.Height) { preferredSize.Height = constrainingSize.Height; } return preferredSize; } private static bool LeftMouseButtonIsDown() { return (Control.MouseButtons == MouseButtons.Left) && (Control.ModifierKeys == Keys.None); } protected override void OnPaint(PaintEventArgs e) { // all the grip painting should be on the ToolStrip itself. ParentInternal?.OnPaintGrip(e); } /// <summary> /// </summary> /// <param name="mea"></param> protected override void OnMouseDown(MouseEventArgs mea) { _startLocation = TranslatePoint(new Point(mea.X, mea.Y), ToolStripPointType.ToolStripItemCoords, ToolStripPointType.ScreenCoords); base.OnMouseDown(mea); } protected override void OnMouseMove(MouseEventArgs mea) { bool leftMouseButtonDown = LeftMouseButtonIsDown(); if (!MovingToolStrip && leftMouseButtonDown) { // determine if we've moved far enough such that the toolstrip // can be considered as moving. Point currentLocation = TranslatePoint(mea.Location, ToolStripPointType.ToolStripItemCoords, ToolStripPointType.ScreenCoords); int deltaX = currentLocation.X - _startLocation.X; deltaX = (deltaX < 0) ? deltaX * -1 : deltaX; if (s_dragSize == LayoutUtils.s_maxSize) { s_dragSize = SystemInformation.DragSize; } if (deltaX >= s_dragSize.Width) { MovingToolStrip = true; } else { int deltaY = currentLocation.Y - _startLocation.Y; deltaY = (deltaY < 0) ? deltaY * -1 : deltaY; if (deltaY >= s_dragSize.Height) { MovingToolStrip = true; } } } if (MovingToolStrip) { if (leftMouseButtonDown) { Point endLocation = TranslatePoint(new Point(mea.X, mea.Y), ToolStripPointType.ToolStripItemCoords, ToolStripPointType.ScreenCoords); // protect against calling when the mouse hasn't really moved. Moving the toolstrip/creating the feedback rect // can cause extra mousemove events, we want to make sure we're not doing all this work // for nothing. if (endLocation != _lastEndLocation) { ToolStripPanelRow.ToolStripPanel.MoveControl(ParentInternal, /*startLocation,*/endLocation); _lastEndLocation = endLocation; } _startLocation = endLocation; } else { // sometimes we don't get mouseup in DT. Release now. MovingToolStrip = false; } } base.OnMouseMove(mea); } protected override void OnMouseEnter(EventArgs e) { // only switch the cursor if we've got a rafting row. if ((ParentInternal is not null) && (ToolStripPanelRow is not null) && (!ParentInternal.IsInDesignMode)) { _oldCursor = ParentInternal.Cursor; ParentInternal.Cursor = Cursors.SizeAll; } else { _oldCursor = null; } base.OnMouseEnter(e); } protected override void OnMouseLeave(EventArgs e) { if (_oldCursor is not null && ParentInternal is not null && !ParentInternal.IsInDesignMode) { ParentInternal.Cursor = _oldCursor; } if (!MovingToolStrip && LeftMouseButtonIsDown()) { MovingToolStrip = true; } base.OnMouseLeave(e); } protected override void OnMouseUp(MouseEventArgs mea) { if (MovingToolStrip) { Point endLocation = TranslatePoint(new Point(mea.X, mea.Y), ToolStripPointType.ToolStripItemCoords, ToolStripPointType.ScreenCoords); ToolStripPanelRow.ToolStripPanel.MoveControl(ParentInternal, /*startLocation,*/endLocation); } if (ParentInternal is not null && !ParentInternal.IsInDesignMode) { ParentInternal.Cursor = _oldCursor; } ToolStripPanel.ClearDragFeedback(); MovingToolStrip = false; base.OnMouseUp(mea); } internal override void ToolStrip_RescaleConstants(int oldDpi, int newDpi) { RescaleConstantsInternal(newDpi); ScaleConstants(newDpi); Margin = DefaultMargin; OnFontChanged(EventArgs.Empty); } private void ScaleConstants(int dpi) { const int LogicalDefaultPadding = 2; const int LogicalGripThickness = 3; const int LogicalGripThicknessVisualStylesEnabled = 5; _defaultPadding = new(ScaleHelper.ScaleToDpi(LogicalDefaultPadding, dpi)); GripThickness = ScaleHelper.ScaleToDpi( ToolStripManager.VisualStylesEnabled ? LogicalGripThicknessVisualStylesEnabled : LogicalGripThickness, dpi); } }