fix(Touch):添加控制点触控支持以及移动墨迹问题 (#374)

* feat(MW_SelectionGestures.cs): 为缩放选择框添加触摸事件

Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com>

* refactor(MW_SelectionGestures.cs): 清理PreviewTouch

Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com>

* fix(MW_SelectionGestures.cs): 单指触摸时阻止缩放处理以允许拖动操作

当检测到单指触摸且存在选中笔迹时,直接返回以允许TouchMove处理拖动操作,避免与缩放手势冲突

Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com>

---------

Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com>
This commit is contained in:
doudou0720
2026-02-16 17:15:33 +08:00
committed by GitHub
parent 78302ca426
commit 2f8c368eef
2 changed files with 108 additions and 99 deletions
+19 -14
View File
@@ -4451,12 +4451,9 @@
ManipulationStarting="GridInkCanvasSelectionCover_ManipulationStarting"
ManipulationCompleted="GridInkCanvasSelectionCover_ManipulationCompleted"
ManipulationDelta="GridInkCanvasSelectionCover_ManipulationDelta"
PreviewTouchDown="GridInkCanvasSelectionCover_PreviewTouchDown"
PreviewTouchUp="GridInkCanvasSelectionCover_PreviewTouchUp"
PreviewTouchMove="GridInkCanvasSelectionCover_PreviewTouchMove"
TouchDown="GridInkCanvasSelectionCover_TouchDown"
TouchUp="GridInkCanvasSelectionCover_TouchUp"
TouchMove="GridInkCanvasSelectionCover_TouchMove"
TouchDown="GridInkCanvasSelectionCover_TouchDown"
TouchUp="GridInkCanvasSelectionCover_TouchUp"
TouchMove="GridInkCanvasSelectionCover_TouchMove"
Background="#01FFFFFF" Opacity="0.01" Visibility="Visible" Margin="1,0,-1,0">
<!-- 选择框 -->
@@ -4474,23 +4471,31 @@
<Canvas Name="SelectionHandlesCanvas" Visibility="Collapsed">
<!-- 四个角选择点 -->
<Rectangle Name="TopLeftHandle" Width="8" Height="8" Fill="LightBlue" Stroke="Blue" StrokeThickness="1"
Cursor="SizeNWSE" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp" />
Cursor="SizeNWSE" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp"
TouchDown="SelectionHandle_TouchDown" TouchMove="SelectionHandle_TouchMove" TouchUp="SelectionHandle_TouchUp" />
<Rectangle Name="TopRightHandle" Width="8" Height="8" Fill="LightBlue" Stroke="Blue" StrokeThickness="1"
Cursor="SizeNESW" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp" />
Cursor="SizeNESW" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp"
TouchDown="SelectionHandle_TouchDown" TouchMove="SelectionHandle_TouchMove" TouchUp="SelectionHandle_TouchUp" />
<Rectangle Name="BottomLeftHandle" Width="8" Height="8" Fill="LightBlue" Stroke="Blue" StrokeThickness="1"
Cursor="SizeNESW" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp" />
Cursor="SizeNESW" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp"
TouchDown="SelectionHandle_TouchDown" TouchMove="SelectionHandle_TouchMove" TouchUp="SelectionHandle_TouchUp" />
<Rectangle Name="BottomRightHandle" Width="8" Height="8" Fill="LightBlue" Stroke="Blue" StrokeThickness="1"
Cursor="SizeNWSE" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp" />
Cursor="SizeNWSE" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp"
TouchDown="SelectionHandle_TouchDown" TouchMove="SelectionHandle_TouchMove" TouchUp="SelectionHandle_TouchUp" />
<!-- 四个边选择点 -->
<Rectangle Name="TopHandle" Width="8" Height="8" Fill="LightBlue" Stroke="Blue" StrokeThickness="1"
Cursor="SizeNS" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp" />
Cursor="SizeNS" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp"
TouchDown="SelectionHandle_TouchDown" TouchMove="SelectionHandle_TouchMove" TouchUp="SelectionHandle_TouchUp" />
<Rectangle Name="BottomHandle" Width="8" Height="8" Fill="LightBlue" Stroke="Blue" StrokeThickness="1"
Cursor="SizeNS" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp" />
Cursor="SizeNS" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp"
TouchDown="SelectionHandle_TouchDown" TouchMove="SelectionHandle_TouchMove" TouchUp="SelectionHandle_TouchUp" />
<Rectangle Name="LeftHandle" Width="8" Height="8" Fill="LightBlue" Stroke="Blue" StrokeThickness="1"
Cursor="SizeWE" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp" />
Cursor="SizeWE" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp"
TouchDown="SelectionHandle_TouchDown" TouchMove="SelectionHandle_TouchMove" TouchUp="SelectionHandle_TouchUp" />
<Rectangle Name="RightHandle" Width="8" Height="8" Fill="LightBlue" Stroke="Blue" StrokeThickness="1"
Cursor="SizeWE" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp" />
Cursor="SizeWE" MouseDown="SelectionHandle_MouseDown" MouseMove="SelectionHandle_MouseMove" MouseUp="SelectionHandle_MouseUp"
TouchDown="SelectionHandle_TouchDown" TouchMove="SelectionHandle_TouchMove" TouchUp="SelectionHandle_TouchUp" />
</Canvas>
</Grid>
<Border Name="BorderStrokeSelectionControl"
@@ -496,6 +496,12 @@ namespace Ink_Canvas
{
if (dec.Count >= 1)
{
// 单指时,让TouchMove处理拖动
if (dec.Count == 1 && inkCanvas.GetSelectedStrokes().Count > 0)
{
return;
}
bool disableScale = dec.Count >= 3;
var md = e.DeltaManipulation;
var trans = md.Translation; // 获得位移矢量
@@ -539,10 +545,51 @@ namespace Ink_Canvas
private void GridInkCanvasSelectionCover_TouchDown(object sender, TouchEventArgs e)
{
dec.Add(e.TouchDevice.Id);
//设备1个的时候,记录中心点
if (dec.Count == 1)
{
var touchPoint = e.GetTouchPoint(null);
centerPoint = touchPoint.Position;
lastTouchPointOnGridInkCanvasCover = touchPoint.Position;
}
}
private void GridInkCanvasSelectionCover_TouchUp(object sender, TouchEventArgs e)
{
dec.Remove(e.TouchDevice.Id);
if (dec.Count >= 1) return;
isProgramChangeStrokeSelection = false;
var touchUpPoint = e.GetTouchPoint(null).Position;
if (lastTouchPointOnGridInkCanvasCover == touchUpPoint)
{
var touchPointInCanvas = e.GetTouchPoint(inkCanvas).Position;
var selectionBounds = inkCanvas.GetSelectionBounds();
if (!(touchPointInCanvas.X < selectionBounds.Left) &&
!(touchPointInCanvas.Y < selectionBounds.Top) &&
!(touchPointInCanvas.X > selectionBounds.Right) &&
!(touchPointInCanvas.Y > selectionBounds.Bottom))
{
return;
}
isProgramChangeStrokeSelection = true;
inkCanvas.Select(new StrokeCollection());
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
isProgramChangeStrokeSelection = false;
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 GridInkCanvasSelectionCover_TouchMove(object sender, TouchEventArgs e)
@@ -581,93 +628,8 @@ namespace Ink_Canvas
}
}
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 = touchPoint.Position;
}
}
private void GridInkCanvasSelectionCover_PreviewTouchUp(object sender, TouchEventArgs e)
{
dec.Remove(e.TouchDevice.Id);
if (dec.Count >= 1) return;
isProgramChangeStrokeSelection = false;
var touchUpPoint = e.GetTouchPoint(null).Position;
if (lastTouchPointOnGridInkCanvasCover == touchUpPoint)
{
var touchPointInCanvas = e.GetTouchPoint(inkCanvas).Position;
var selectionBounds = inkCanvas.GetSelectionBounds();
if (!(touchPointInCanvas.X < selectionBounds.Left) &&
!(touchPointInCanvas.Y < selectionBounds.Top) &&
!(touchPointInCanvas.X > selectionBounds.Right) &&
!(touchPointInCanvas.Y > selectionBounds.Bottom))
{
return;
}
isProgramChangeStrokeSelection = true;
inkCanvas.Select(new StrokeCollection());
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
isProgramChangeStrokeSelection = false;
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)
{
forceEraser = false;
@@ -818,6 +780,48 @@ namespace Ink_Canvas
}
}
private void SelectionHandle_TouchDown(object sender, TouchEventArgs e)
{
if (sender is Rectangle handle)
{
isResizing = true;
currentResizeHandle = handle.Name;
var touchPoint = e.GetTouchPoint(inkCanvas);
resizeStartPoint = touchPoint.Position;
originalSelectionBounds = inkCanvas.GetSelectionBounds();
e.Handled = true;
}
}
private void SelectionHandle_TouchMove(object sender, TouchEventArgs e)
{
if (!isResizing || !(sender is Rectangle handle)) return;
var touchPoint = e.GetTouchPoint(inkCanvas);
var currentPoint = touchPoint.Position;
var delta = new Point(currentPoint.X - resizeStartPoint.X, currentPoint.Y - resizeStartPoint.Y);
var newBounds = CalculateNewBounds(originalSelectionBounds, delta, currentResizeHandle);
// 应用新的边界到选中的墨迹
ApplyBoundsToStrokes(newBounds);
// 更新选择框显示
UpdateSelectionDisplay();
e.Handled = true;
}
private void SelectionHandle_TouchUp(object sender, TouchEventArgs e)
{
if (sender is Rectangle handle)
{
isResizing = false;
currentResizeHandle = "";
e.Handled = true;
}
}
private Rect CalculateNewBounds(Rect originalBounds, Point delta, string handleName)
{
var newBounds = originalBounds;