Files
community/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs
T
2025-09-07 07:53:05 +08:00

955 lines
39 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using Ink_Canvas.Helpers;
using Point = System.Windows.Point;
namespace Ink_Canvas
{
public partial class MainWindow : Window
{
#region Floating Control
private object lastBorderMouseDownObject;
private void Border_MouseDown(object sender, MouseButtonEventArgs e)
{
// 如果发送者是 RandomDrawPanel 或 SingleDrawPanel,且它们被隐藏,则不处理事件
if (sender is SimpleStackPanel panel)
{
if ((panel == RandomDrawPanel || panel == SingleDrawPanel) &&
panel.Visibility != Visibility.Visible)
{
return;
}
}
lastBorderMouseDownObject = sender;
}
private bool isStrokeSelectionCloneOn;
private void BorderStrokeSelectionClone_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
if (isStrokeSelectionCloneOn)
{
BorderStrokeSelectionClone.Background = Brushes.Transparent;
isStrokeSelectionCloneOn = false;
}
else
{
BorderStrokeSelectionClone.Background = new SolidColorBrush(StringToColor("#FF1ED760"));
isStrokeSelectionCloneOn = true;
}
}
private void BorderStrokeSelectionCloneToNewBoard_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
var strokes = inkCanvas.GetSelectedStrokes();
inkCanvas.Select(new StrokeCollection());
strokes = strokes.Clone();
BtnWhiteBoardAdd_Click(null, null);
inkCanvas.Strokes.Add(strokes);
}
private void BorderStrokeSelectionDelete_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
SymbolIconDelete_MouseUp(sender, e);
}
private void GridPenWidthDecrease_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
ChangeStrokeThickness(0.8);
}
private void GridPenWidthIncrease_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
ChangeStrokeThickness(1.25);
}
private void ChangeStrokeThickness(double multipler)
{
foreach (var stroke in inkCanvas.GetSelectedStrokes())
{
var newWidth = stroke.DrawingAttributes.Width * multipler;
var newHeight = stroke.DrawingAttributes.Height * multipler;
if (!(newWidth >= DrawingAttributes.MinWidth) || !(newWidth <= DrawingAttributes.MaxWidth)
|| !(newHeight >= DrawingAttributes.MinHeight) ||
!(newHeight <= DrawingAttributes.MaxHeight)) continue;
stroke.DrawingAttributes.Width = newWidth;
stroke.DrawingAttributes.Height = newHeight;
}
if (DrawingAttributesHistory.Count > 0)
{
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
private void GridPenWidthRestore_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
foreach (var stroke in inkCanvas.GetSelectedStrokes())
{
stroke.DrawingAttributes.Width = inkCanvas.DefaultDrawingAttributes.Width;
stroke.DrawingAttributes.Height = inkCanvas.DefaultDrawingAttributes.Height;
}
}
private void ImageFlipHorizontal_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.ScaleAt(-1, 1, center.X, center.Y); // 缩放
var targetStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in targetStrokes) stroke.Transform(m, false);
if (DrawingAttributesHistory.Count > 0)
{
//var collecion = new StrokeCollection();
//foreach (var item in DrawingAttributesHistory)
//{
// collecion.Add(item.Key);
//}
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
//updateBorderStrokeSelectionControlLocation();
}
private void ImageFlipVertical_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.ScaleAt(1, -1, center.X, center.Y); // 缩放
var targetStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in targetStrokes) stroke.Transform(m, false);
if (DrawingAttributesHistory.Count > 0)
{
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
// ... existing code ...
private void ImageRotate45_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.RotateAt(45, center.X, center.Y); // 顺时针旋转45度
var targetStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in targetStrokes) stroke.Transform(m, false);
if (DrawingAttributesHistory.Count > 0)
{
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
private void ImageRotate90_MouseUp(object sender, MouseButtonEventArgs e)
{
if (lastBorderMouseDownObject != sender) return;
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.RotateAt(90, center.X, center.Y); // 旋转
var targetStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in targetStrokes) stroke.Transform(m, false);
if (DrawingAttributesHistory.Count > 0)
{
var collecion = new StrokeCollection();
foreach (var item in DrawingAttributesHistory)
{
collecion.Add(item.Key);
}
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
#endregion
private bool isGridInkCanvasSelectionCoverMouseDown;
private bool isStrokeDragging = false;
private Point strokeDragStartPoint;
private StrokeCollection StrokesSelectionClone = new StrokeCollection();
// 选择框和选择点相关变量
private bool isResizing = false;
private string currentResizeHandle = "";
private Point resizeStartPoint;
private Rect originalSelectionBounds;
private void GridInkCanvasSelectionCover_MouseDown(object sender, MouseButtonEventArgs e)
{
isGridInkCanvasSelectionCoverMouseDown = true;
// 检查是否有选中的墨迹
if (inkCanvas.GetSelectedStrokes().Count > 0)
{
// 获取鼠标点击位置
var clickPoint = e.GetPosition(inkCanvas);
var selectionBounds = inkCanvas.GetSelectionBounds();
// 检查点击位置是否在选择框边界内
if (clickPoint.X >= selectionBounds.Left &&
clickPoint.X <= selectionBounds.Right &&
clickPoint.Y >= selectionBounds.Top &&
clickPoint.Y <= selectionBounds.Bottom)
{
// 只有在选择框边界内才允许拖动
isStrokeDragging = true;
strokeDragStartPoint = clickPoint;
GridInkCanvasSelectionCover.CaptureMouse();
GridInkCanvasSelectionCover.Cursor = Cursors.SizeAll;
}
else
{
// 点击在选择框外,取消选择
inkCanvas.Select(new StrokeCollection());
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
}
}
}
private void GridInkCanvasSelectionCover_MouseMove(object sender, MouseEventArgs e)
{
if (!isGridInkCanvasSelectionCoverMouseDown) return;
// 如果正在拖动墨迹,执行拖动操作
if (isStrokeDragging && GridInkCanvasSelectionCover.IsMouseCaptured)
{
var currentPoint = e.GetPosition(inkCanvas);
var delta = currentPoint - strokeDragStartPoint;
// 创建变换矩阵
var matrix = new Matrix();
matrix.Translate(delta.X, delta.Y);
// 对选中的墨迹应用变换
var selectedStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in selectedStrokes)
{
stroke.Transform(matrix, false);
}
// 更新选中栏位置
updateBorderStrokeSelectionControlLocation();
// 更新起始点
strokeDragStartPoint = currentPoint;
}
else if (inkCanvas.GetSelectedStrokes().Count > 0)
{
// 当鼠标在选中区域移动时,更新墨迹选中栏位置
updateBorderStrokeSelectionControlLocation();
}
}
private void GridInkCanvasSelectionCover_MouseUp(object sender, MouseButtonEventArgs e)
{
if (!isGridInkCanvasSelectionCoverMouseDown) return;
// 结束墨迹拖动
if (isStrokeDragging)
{
isStrokeDragging = false;
GridInkCanvasSelectionCover.ReleaseMouseCapture();
GridInkCanvasSelectionCover.Cursor = Cursors.Arrow;
}
isGridInkCanvasSelectionCoverMouseDown = false;
// 只有在没有选中墨迹时才隐藏选中栏
if (inkCanvas.GetSelectedStrokes().Count == 0)
{
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
}
}
private void BtnSelect_Click(object sender, RoutedEventArgs e)
{
ExitMultiTouchModeIfNeeded();
forceEraser = true;
drawingShapeMode = 0;
inkCanvas.IsManipulationEnabled = false;
if (inkCanvas.EditingMode == InkCanvasEditingMode.Select)
{
if (inkCanvas.GetSelectedStrokes().Count == inkCanvas.Strokes.Count)
{
// 使用集中化的工具模式切换方法
SetCurrentToolMode(InkCanvasEditingMode.Ink,
() => { SetCurrentToolMode(InkCanvasEditingMode.Select); });
}
else
{
var selectedStrokes = new StrokeCollection();
foreach (var stroke in inkCanvas.Strokes)
if (stroke.GetBounds().Width > 0 && stroke.GetBounds().Height > 0)
selectedStrokes.Add(stroke);
inkCanvas.Select(selectedStrokes);
}
}
else
{
// 使用集中化的工具模式切换方法
SetCurrentToolMode(InkCanvasEditingMode.Select);
}
}
private double BorderStrokeSelectionControlWidth = 490.0;
private double BorderStrokeSelectionControlHeight = 80.0;
private bool isProgramChangeStrokeSelection;
private void inkCanvas_SelectionChanged(object sender, EventArgs e)
{
if (isProgramChangeStrokeSelection) return;
// 优先检查墨迹选择状态
if (inkCanvas.GetSelectedStrokes().Count > 0)
{
// 有墨迹被选中,清除图片选择状态
if (currentSelectedElement != null)
{
currentSelectedElement = null;
// 隐藏图片选择工具栏
if (BorderImageSelectionControl != null)
{
BorderImageSelectionControl.Visibility = Visibility.Collapsed;
}
}
// 显示墨迹选择栏和选择框
GridInkCanvasSelectionCover.Visibility = Visibility.Visible;
BorderStrokeSelectionClone.Background = Brushes.Transparent;
isStrokeSelectionCloneOn = false;
updateBorderStrokeSelectionControlLocation();
UpdateSelectionDisplay();
return;
}
// 检查是否有图片元素被选中(通过InkCanvas的选中元素)
var selectedElements = inkCanvas.GetSelectedElements();
bool hasImageElement = selectedElements.Any(element => element is Image);
// 如果有图片元素被选中,不显示选择框
if (hasImageElement)
{
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
HideSelectionDisplay();
return;
}
// 检查是否有图片元素被选中(通过currentSelectedElement
if (currentSelectedElement != null && currentSelectedElement is Image)
{
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
HideSelectionDisplay();
return;
}
// 没有选中任何内容,隐藏选择框
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
HideSelectionDisplay();
}
private void updateBorderStrokeSelectionControlLocation()
{
var borderLeft = (inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Right -
BorderStrokeSelectionControlWidth) / 2;
var borderTop = inkCanvas.GetSelectionBounds().Bottom + 10; // 在墨迹下方10像素处显示
if (borderLeft < 0) borderLeft = 0;
if (borderTop < 0) borderTop = 0;
if (Width - borderLeft < BorderStrokeSelectionControlWidth || double.IsNaN(borderLeft))
borderLeft = Width - BorderStrokeSelectionControlWidth;
if (Height - borderTop < BorderStrokeSelectionControlHeight || double.IsNaN(borderTop))
borderTop = Height - BorderStrokeSelectionControlHeight;
// 确保墨迹选中栏始终显示在墨迹下方
// 如果选中栏会超出屏幕底部,则显示在墨迹上方
if (borderTop + BorderStrokeSelectionControlHeight > Height)
{
borderTop = inkCanvas.GetSelectionBounds().Top - BorderStrokeSelectionControlHeight - 10;
if (borderTop < 0) borderTop = 10; // 如果上方也没有空间,则显示在顶部
}
BorderStrokeSelectionControl.Margin = new Thickness(borderLeft, borderTop, 0, 0);
}
private void GridInkCanvasSelectionCover_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
e.Mode = ManipulationModes.All;
}
private void GridInkCanvasSelectionCover_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
if (StrokeManipulationHistory?.Count > 0)
{
timeMachine.CommitStrokeManipulationHistory(StrokeManipulationHistory);
foreach (var item in StrokeManipulationHistory)
{
StrokeInitialHistory[item.Key] = item.Value.Item2;
}
StrokeManipulationHistory = null;
}
if (DrawingAttributesHistory.Count > 0)
{
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
private void GridInkCanvasSelectionCover_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
try
{
if (dec.Count >= 1)
{
bool disableScale = dec.Count >= 3;
var md = e.DeltaManipulation;
var trans = md.Translation; // 获得位移矢量
var rotate = md.Rotation; // 获得旋转角度
var scale = md.Scale; // 获得缩放倍数
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.Translate(trans.X, trans.Y); // 移动
if (!disableScale)
m.ScaleAt(scale.X, scale.Y, center.X, center.Y); // 缩放
var strokes = inkCanvas.GetSelectedStrokes();
if (StrokesSelectionClone.Count != 0)
strokes = StrokesSelectionClone;
else if (Settings.Gesture.IsEnableTwoFingerRotationOnSelection)
m.RotateAt(rotate, center.X, center.Y); // 旋转
// 应用变换到选中的墨迹
foreach (var stroke in strokes)
{
stroke.Transform(m, false);
}
updateBorderStrokeSelectionControlLocation();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"墨迹ManipulationDelta错误: {ex.Message}", LogHelper.LogType.Error);
}
}
private void GridInkCanvasSelectionCover_TouchDown(object sender, TouchEventArgs e)
{
}
private void GridInkCanvasSelectionCover_TouchUp(object sender, TouchEventArgs e)
{
}
private void GridInkCanvasSelectionCover_TouchMove(object sender, TouchEventArgs e)
{
// 处理触摸移动事件 - 用于拖动选中的墨迹
if (inkCanvas.GetSelectedStrokes().Count > 0 && dec.Count == 1)
{
var currentTouchPoint = e.GetTouchPoint(inkCanvas).Position;
// 检查是否有有效的起始触摸点
if (lastTouchPointOnGridInkCanvasCover != new Point(0, 0))
{
var delta = currentTouchPoint - lastTouchPointOnGridInkCanvasCover;
// 只有当移动距离足够大时才进行拖动(避免微小移动造成的抖动)
if (Math.Abs(delta.X) > 1 || Math.Abs(delta.Y) > 1)
{
// 创建变换矩阵
var matrix = new Matrix();
matrix.Translate(delta.X, delta.Y);
// 对选中的墨迹应用变换
var selectedStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in selectedStrokes)
{
stroke.Transform(matrix, false);
}
// 更新选中栏位置
updateBorderStrokeSelectionControlLocation();
// 更新最后触摸点
lastTouchPointOnGridInkCanvasCover = currentTouchPoint;
}
}
}
}
private void GridInkCanvasSelectionCover_PreviewTouchMove(object sender, TouchEventArgs e)
{
// 预览触摸移动事件 - 用于更精确的触摸处理
if (inkCanvas.GetSelectedStrokes().Count > 0 && dec.Count == 1)
{
var currentTouchPoint = e.GetTouchPoint(inkCanvas).Position;
// 检查是否有有效的起始触摸点
if (lastTouchPointOnGridInkCanvasCover != new Point(0, 0))
{
var delta = currentTouchPoint - lastTouchPointOnGridInkCanvasCover;
// 只有当移动距离足够大时才进行拖动(避免微小移动造成的抖动)
if (Math.Abs(delta.X) > 1 || Math.Abs(delta.Y) > 1)
{
// 创建变换矩阵
var matrix = new Matrix();
matrix.Translate(delta.X, delta.Y);
// 对选中的墨迹应用变换
var selectedStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in selectedStrokes)
{
stroke.Transform(matrix, false);
}
// 更新选中栏位置
updateBorderStrokeSelectionControlLocation();
// 更新最后触摸点
lastTouchPointOnGridInkCanvasCover = currentTouchPoint;
}
}
}
}
private Point lastTouchPointOnGridInkCanvasCover = new Point(0, 0);
private void GridInkCanvasSelectionCover_PreviewTouchDown(object sender, TouchEventArgs e)
{
dec.Add(e.TouchDevice.Id);
//设备1个的时候,记录中心点
if (dec.Count == 1)
{
var touchPoint = e.GetTouchPoint(null);
centerPoint = touchPoint.Position;
lastTouchPointOnGridInkCanvasCover = e.GetTouchPoint(inkCanvas).Position;
// 检查是否有选中的墨迹
if (inkCanvas.GetSelectedStrokes().Count > 0)
{
// 获取触摸点位置
var touchPosition = e.GetTouchPoint(inkCanvas).Position;
var selectionBounds = inkCanvas.GetSelectionBounds();
// 检查触摸位置是否在选择框边界内
if (touchPosition.X >= selectionBounds.Left &&
touchPosition.X <= selectionBounds.Right &&
touchPosition.Y >= selectionBounds.Top &&
touchPosition.Y <= selectionBounds.Bottom)
{
// 只有在选择框边界内才允许拖动
// 触摸拖动状态已通过TouchMove事件处理
}
else
{
// 触摸在选择框外,取消选择
inkCanvas.Select(new StrokeCollection());
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
return;
}
}
if (isStrokeSelectionCloneOn)
{
var strokes = inkCanvas.GetSelectedStrokes();
isProgramChangeStrokeSelection = true;
inkCanvas.Select(new StrokeCollection());
StrokesSelectionClone = strokes.Clone();
inkCanvas.Select(strokes);
isProgramChangeStrokeSelection = false;
inkCanvas.Strokes.Add(StrokesSelectionClone);
}
else
{
// 新增:启动套索选择模式
// 使用集中化的工具模式切换方法
SetCurrentToolMode(InkCanvasEditingMode.Select);
inkCanvas.Select(new StrokeCollection());
}
}
}
private void GridInkCanvasSelectionCover_PreviewTouchUp(object sender, TouchEventArgs e)
{
dec.Remove(e.TouchDevice.Id);
if (dec.Count >= 1) return;
// 重置触摸状态
lastTouchPointOnGridInkCanvasCover = new Point(0, 0);
isProgramChangeStrokeSelection = false;
// 检查是否有点击(没有移动)
var currentTouchPoint = e.GetTouchPoint(null).Position;
if (Math.Abs(currentTouchPoint.X - centerPoint.X) < 5 && Math.Abs(currentTouchPoint.Y - centerPoint.Y) < 5)
{
// 点击在选择框内,保持选择状态
if (inkCanvas.GetSelectedStrokes().Count > 0)
{
var selectionBounds = inkCanvas.GetSelectionBounds();
if (currentTouchPoint.X >= selectionBounds.Left &&
currentTouchPoint.X <= selectionBounds.Right &&
currentTouchPoint.Y >= selectionBounds.Top &&
currentTouchPoint.Y <= selectionBounds.Bottom)
{
// 点击在选择框内,保持选择
GridInkCanvasSelectionCover.Visibility = Visibility.Visible;
StrokesSelectionClone = new StrokeCollection();
return;
}
}
// 点击在选择框外,取消选择
inkCanvas.Select(new StrokeCollection());
StrokesSelectionClone = new StrokeCollection();
}
else if (inkCanvas.GetSelectedStrokes().Count == 0)
{
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
StrokesSelectionClone = new StrokeCollection();
}
else
{
GridInkCanvasSelectionCover.Visibility = Visibility.Visible;
StrokesSelectionClone = new StrokeCollection();
}
}
private void LassoSelect_Click(object sender, RoutedEventArgs e)
{
ExitMultiTouchModeIfNeeded();
forceEraser = false;
forcePointEraser = false;
drawingShapeMode = 0;
// 使用集中化的工具模式切换方法
SetCurrentToolMode(InkCanvasEditingMode.Select);
SetCursorBasedOnEditingMode(inkCanvas);
}
private void BtnLassoSelect_Click(object sender, RoutedEventArgs e)
{
ExitMultiTouchModeIfNeeded();
forceEraser = false;
forcePointEraser = false;
drawingShapeMode = 0;
// 使用集中化的工具模式切换方法
SetCurrentToolMode(InkCanvasEditingMode.Select);
inkCanvas.IsManipulationEnabled = true;
SetCursorBasedOnEditingMode(inkCanvas);
}
#region UIElement Selection and Resize
private Rect GetUIElementBounds(UIElement element)
{
if (element is FrameworkElement fe)
{
var left = InkCanvas.GetLeft(element);
var top = InkCanvas.GetTop(element);
if (double.IsNaN(left)) left = 0;
if (double.IsNaN(top)) top = 0;
var width = fe.ActualWidth > 0 ? fe.ActualWidth : fe.Width;
var height = fe.ActualHeight > 0 ? fe.ActualHeight : fe.Height;
// 检查是否有RenderTransform
if (fe.RenderTransform != null && fe.RenderTransform != Transform.Identity)
{
try
{
// 如果有变换,使用变换后的边界
var transform = element.TransformToAncestor(inkCanvas);
var elementBounds = new Rect(0, 0, width, height);
var transformedBounds = transform.TransformBounds(elementBounds);
return transformedBounds;
}
catch
{
// 变换失败时回退到简单计算
return new Rect(left, top, width, height);
}
}
// 没有变换时直接使用位置和大小
return new Rect(left, top, width, height);
}
return new Rect(0, 0, 0, 0);
}
#endregion
#region Selection Display and Resize Handles
private void UpdateSelectionDisplay()
{
if (inkCanvas.GetSelectedStrokes().Count == 0)
{
HideSelectionDisplay();
return;
}
var selectionBounds = inkCanvas.GetSelectionBounds();
// 更新选择框
SelectionRectangle.Visibility = Visibility.Visible;
SelectionRectangle.Margin = new Thickness(selectionBounds.Left, selectionBounds.Top, 0, 0);
SelectionRectangle.Width = selectionBounds.Width;
SelectionRectangle.Height = selectionBounds.Height;
// 更新选择点位置
UpdateSelectionHandles(selectionBounds);
SelectionHandlesCanvas.Visibility = Visibility.Visible;
}
private void HideSelectionDisplay()
{
SelectionRectangle.Visibility = Visibility.Collapsed;
SelectionHandlesCanvas.Visibility = Visibility.Collapsed;
}
private void UpdateSelectionHandles(Rect bounds)
{
// 四个角选择点
TopLeftHandle.Margin = new Thickness(bounds.Left - 4, bounds.Top - 4, 0, 0);
TopRightHandle.Margin = new Thickness(bounds.Right - 4, bounds.Top - 4, 0, 0);
BottomLeftHandle.Margin = new Thickness(bounds.Left - 4, bounds.Bottom - 4, 0, 0);
BottomRightHandle.Margin = new Thickness(bounds.Right - 4, bounds.Bottom - 4, 0, 0);
// 四个边选择点
TopHandle.Margin = new Thickness(bounds.Left + bounds.Width / 2 - 4, bounds.Top - 4, 0, 0);
BottomHandle.Margin = new Thickness(bounds.Left + bounds.Width / 2 - 4, bounds.Bottom - 4, 0, 0);
LeftHandle.Margin = new Thickness(bounds.Left - 4, bounds.Top + bounds.Height / 2 - 4, 0, 0);
RightHandle.Margin = new Thickness(bounds.Right - 4, bounds.Top + bounds.Height / 2 - 4, 0, 0);
}
private void SelectionHandle_MouseDown(object sender, MouseButtonEventArgs e)
{
if (sender is Rectangle handle)
{
isResizing = true;
currentResizeHandle = handle.Name;
resizeStartPoint = e.GetPosition(inkCanvas);
originalSelectionBounds = inkCanvas.GetSelectionBounds();
handle.CaptureMouse();
e.Handled = true;
}
}
private void SelectionHandle_MouseMove(object sender, MouseEventArgs e)
{
if (!isResizing || !(sender is Rectangle handle)) return;
var currentPoint = e.GetPosition(inkCanvas);
var delta = new Point(currentPoint.X - resizeStartPoint.X, currentPoint.Y - resizeStartPoint.Y);
var newBounds = CalculateNewBounds(originalSelectionBounds, delta, currentResizeHandle);
// 应用新的边界到选中的墨迹
ApplyBoundsToStrokes(newBounds);
// 更新选择框显示
UpdateSelectionDisplay();
}
private void SelectionHandle_MouseUp(object sender, MouseButtonEventArgs e)
{
if (sender is Rectangle handle)
{
isResizing = false;
currentResizeHandle = "";
handle.ReleaseMouseCapture();
e.Handled = true;
}
}
private Rect CalculateNewBounds(Rect originalBounds, Point delta, string handleName)
{
var newBounds = originalBounds;
switch (handleName)
{
case "TopLeftHandle":
newBounds.X = originalBounds.X + delta.X;
newBounds.Y = originalBounds.Y + delta.Y;
newBounds.Width = originalBounds.Width - delta.X;
newBounds.Height = originalBounds.Height - delta.Y;
break;
case "TopRightHandle":
newBounds.Y = originalBounds.Y + delta.Y;
newBounds.Width = originalBounds.Width + delta.X;
newBounds.Height = originalBounds.Height - delta.Y;
break;
case "BottomLeftHandle":
newBounds.X = originalBounds.X + delta.X;
newBounds.Width = originalBounds.Width - delta.X;
newBounds.Height = originalBounds.Height + delta.Y;
break;
case "BottomRightHandle":
newBounds.Width = originalBounds.Width + delta.X;
newBounds.Height = originalBounds.Height + delta.Y;
break;
case "TopHandle":
newBounds.Y = originalBounds.Y + delta.Y;
newBounds.Height = originalBounds.Height - delta.Y;
break;
case "BottomHandle":
newBounds.Height = originalBounds.Height + delta.Y;
break;
case "LeftHandle":
newBounds.X = originalBounds.X + delta.X;
newBounds.Width = originalBounds.Width - delta.X;
break;
case "RightHandle":
newBounds.Width = originalBounds.Width + delta.X;
break;
}
// 确保最小尺寸
if (newBounds.Width < 10) newBounds.Width = 10;
if (newBounds.Height < 10) newBounds.Height = 10;
return newBounds;
}
private void ApplyBoundsToStrokes(Rect newBounds)
{
var selectedStrokes = inkCanvas.GetSelectedStrokes();
if (selectedStrokes.Count == 0) return;
var originalBounds = inkCanvas.GetSelectionBounds();
// 计算缩放比例
var scaleX = newBounds.Width / originalBounds.Width;
var scaleY = newBounds.Height / originalBounds.Height;
// 计算平移量
var translateX = newBounds.X - originalBounds.X;
var translateY = newBounds.Y - originalBounds.Y;
// 创建变换矩阵
var matrix = new Matrix();
matrix.Translate(translateX, translateY);
matrix.ScaleAt(scaleX, scaleY, originalBounds.X + originalBounds.Width / 2, originalBounds.Y + originalBounds.Height / 2);
// 应用变换到选中的墨迹
foreach (var stroke in selectedStrokes)
{
stroke.Transform(matrix, false);
}
}
#endregion
}
}