improve:issue #252

改进手掌擦及手势
This commit is contained in:
2025-12-06 22:55:55 +08:00
parent 82dba31b2a
commit 54b74d7411
2 changed files with 29 additions and 216 deletions
@@ -2897,12 +2897,6 @@ namespace Ink_Canvas
// 清空触摸点计数器
dec.Clear();
// 重置手掌擦状态
if (isPalmEraserActive)
{
isPalmEraserActive = false;
}
// 确保触摸事件能正常响应
inkCanvas.IsHitTestVisible = true;
inkCanvas.IsManipulationEnabled = true;
+29 -210
View File
@@ -571,17 +571,14 @@ namespace Ink_Canvas
}
}
// 手掌擦相关变量
private bool isPalmEraserActive;
private InkCanvasEditingMode palmEraserLastEditingMode = InkCanvasEditingMode.Ink;
private bool palmEraserLastIsHighlighter;
private bool palmEraserWasEnabledBeforeMultiTouch;
public double GetTouchBoundWidth(TouchEventArgs e)
{
var args = e.GetTouchPoint(null).Bounds;
if (!Settings.Advanced.IsQuadIR) return args.Width;
else return Math.Sqrt(args.Width * args.Height); // 四边红外
double value;
if (!Settings.Advanced.IsQuadIR) value = args.Width;
else value = Math.Sqrt(args.Width * args.Height); //四边红外
if (Settings.Advanced.IsSpecialScreen) value *= Settings.Advanced.TouchMultiplier;
return value;
}
private void inkCanvas_PreviewTouchDown(object sender, TouchEventArgs e)
@@ -646,70 +643,6 @@ namespace Ink_Canvas
lastTouchDownTime = DateTime.Now;
dec.Add(e.TouchDevice.Id);
// Palm Eraser 逻辑
if (Settings.Canvas.EnablePalmEraser && !isPalmEraserActive)
{
touchPoint = e.GetTouchPoint(inkCanvas);
double boundWidth = GetTouchBoundWidth(e);
if ((Settings.Advanced.TouchMultiplier != 0 || !Settings.Advanced.IsSpecialScreen)
&& (boundWidth > BoundsWidth))
{
// 根据敏感度调整阈值倍数
double thresholdMultiplier;
switch (Settings.Canvas.PalmEraserSensitivity)
{
case 0: // 低敏感度
thresholdMultiplier = 3.0;
break;
case 1: // 中敏感度
thresholdMultiplier = 2.5;
break;
case 2: // 高敏感度
default:
thresholdMultiplier = 2.0;
break;
}
double EraserThresholdValue = Settings.Startup.IsEnableNibMode ?
Settings.Advanced.NibModeBoundsWidthThresholdValue :
Settings.Advanced.FingerModeBoundsWidthThresholdValue;
if (boundWidth > BoundsWidth * EraserThresholdValue * thresholdMultiplier)
{
// 记录当前编辑模式和高光状态
palmEraserLastEditingMode = inkCanvas.EditingMode;
palmEraserLastIsHighlighter = drawingAttributes.IsHighlighter;
// 动态调整橡皮大小
boundWidth *= (Settings.Startup.IsEnableNibMode ?
Settings.Advanced.NibModeBoundsWidthEraserSize :
Settings.Advanced.FingerModeBoundsWidthEraserSize);
if (Settings.Advanced.IsSpecialScreen)
boundWidth *= Settings.Advanced.TouchMultiplier;
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
isPalmEraserActive = true;
// 启用橡皮擦覆盖层显示手掌擦样式
EnableEraserOverlay();
// 更新橡皮擦大小以匹配手掌擦面积
eraserWidth = boundWidth;
UpdateEraserStyle();
// 显示初始橡皮擦反馈位置
touchPoint = e.GetTouchPoint(inkCanvas);
EraserOverlay_PointerDown(sender);
EraserOverlay_PointerMove(sender, touchPoint.Position);
if (Settings.Canvas.IsShowCursor)
{
inkCanvas.ForceCursor = false;
inkCanvas.UseCustomCursor = false;
}
}
}
}
// 设备1个的时候,记录中心点
if (dec.Count == 1)
{
@@ -778,27 +711,18 @@ namespace Ink_Canvas
private void inkCanvas_PreviewTouchMove(object sender, TouchEventArgs e)
{
// 如果手掌擦激活,更新橡皮擦反馈位置
if (isPalmEraserActive)
{
var touchPoint = e.GetTouchPoint(inkCanvas);
EraserOverlay_PointerMove(sender, touchPoint.Position);
}
}
private void inkCanvas_PreviewTouchUp(object sender, TouchEventArgs e)
{
// 橡皮状态下不做任何切换,直接return,保证橡皮可持续
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint && !isPalmEraserActive)
{
return;
}
inkCanvas.ReleaseAllTouchCaptures();
ViewboxFloatingBar.IsHitTestVisible = true;
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
// Palm Eraser 逻辑
//手势完成后切回之前的状态
if (dec.Count > 1)
if (inkCanvas.EditingMode == InkCanvasEditingMode.None)
inkCanvas.EditingMode = lastInkCanvasEditingMode;
dec.Remove(e.TouchDevice.Id);
// 重置多触控点定时器状态
@@ -846,82 +770,6 @@ namespace Ink_Canvas
}
}
// 手势完成后切回之前的状态
if (drawingShapeMode == 0)
{
if (dec.Count > 1)
{
if (inkCanvas.EditingMode == InkCanvasEditingMode.None)
{
if (lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint)
{
inkCanvas.EditingMode = lastInkCanvasEditingMode;
}
}
}
else if (dec.Count == 0)
{
// 当所有触摸点都抬起时,确保正确恢复编辑模式
// 这对于从橡皮擦切换到笔后恢复多指手势功能很重要
if (inkCanvas.EditingMode == InkCanvasEditingMode.None &&
lastInkCanvasEditingMode != InkCanvasEditingMode.None &&
lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint)
{
inkCanvas.EditingMode = lastInkCanvasEditingMode;
}
if (isPalmEraserActive)
{
LogHelper.WriteLogToFile("Palm eraser force recovery - all touch points cleared");
// 恢复高光状态
drawingAttributes.IsHighlighter = palmEraserLastIsHighlighter;
// 恢复编辑模式
try
{
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint)
{
switch (palmEraserLastEditingMode)
{
case InkCanvasEditingMode.Ink:
PenIcon_Click(null, null);
break;
case InkCanvasEditingMode.Select:
SymbolIconSelect_MouseUp(null, null);
break;
default:
inkCanvas.EditingMode = palmEraserLastEditingMode;
break;
}
LogHelper.WriteLogToFile($"Palm eraser force recovered to mode: {palmEraserLastEditingMode}");
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"Palm eraser force recovery failed: {ex.Message}, forcing to Ink mode", LogHelper.LogType.Error);
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
}
// 如果手掌擦还在激活状态但触摸点已清空,强制重置状态
isPalmEraserActive = false;
inkCanvas.IsHitTestVisible = true;
inkCanvas.IsManipulationEnabled = true;
ViewboxFloatingBar.IsHitTestVisible = true;
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
DisableEraserOverlay();
if (Settings.Canvas.IsShowCursor)
{
inkCanvas.ForceCursor = true;
inkCanvas.UseCustomCursor = true;
}
LogHelper.WriteLogToFile("Palm eraser force recovery completed");
}
}
}
inkCanvas.Opacity = 1;
if (dec.Count == 0)
@@ -956,44 +804,7 @@ namespace Ink_Canvas
private void Main_Grid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
// 手掌擦时禁止移动/缩放
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint)
return;
// 三指及以上禁止缩放
bool disableScale = dec.Count >= 3;
if (isInMultiTouchMode) return;
if (dec.Count == 0 && (isSingleFingerDragMode || isInMultiTouchMode))
{
ResetTouchStates();
return;
}
// 如果是单指拖动选中的墨迹,允许处理
if (dec.Count == 1 && inkCanvas.GetSelectedStrokes().Count > 0)
{
var md = e.DeltaManipulation;
var trans = md.Translation; // 获得位移矢量
if (trans.X != 0 || trans.Y != 0)
{
var m = new Matrix();
m.Translate(trans.X, trans.Y); // 移动
var strokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in strokes)
{
stroke.Transform(m, false);
}
// 更新选择框位置
updateBorderStrokeSelectionControlLocation();
}
return;
}
if (!Settings.Gesture.IsEnableTwoFingerGesture) return;
if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return;
if ((dec.Count >= 2 && (Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode ||
StackPanelPPTControls.Visibility != Visibility.Visible ||
StackPanelPPTButtons.Visibility == Visibility.Collapsed)) ||
@@ -1007,20 +818,23 @@ namespace Ink_Canvas
if (Settings.Gesture.IsEnableTwoFingerTranslate)
m.Translate(trans.X, trans.Y); // 移动
// 计算中心点(用于缩放和旋转)
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
if (Settings.Gesture.IsEnableTwoFingerGestureTranslateOrRotation)
{
var rotate = md.Rotation; // 获得旋转角度
var scale = md.Scale; // 获得缩放倍数
// 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 = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
if (Settings.Gesture.IsEnableTwoFingerRotation)
m.RotateAt(rotate, center.X, center.Y); // 旋转
if (Settings.Gesture.IsEnableTwoFingerZoom && !disableScale)
m.ScaleAt(scale.X, scale.Y, center.X, center.Y); // 缩放
}
if (Settings.Gesture.IsEnableTwoFingerZoom)
{
var scale = md.Scale; // 获得缩放倍数
m.ScaleAt(scale.X, scale.Y, center.X, center.Y); // 缩放
}
var strokes = inkCanvas.GetSelectedStrokes();
@@ -1043,6 +857,13 @@ namespace Ink_Canvas
break;
}
if (!Settings.Gesture.IsEnableTwoFingerZoom) continue;
try
{
stroke.DrawingAttributes.Width *= md.Scale.X;
stroke.DrawingAttributes.Height *= md.Scale.Y;
}
catch { }
}
}
else
@@ -1165,8 +986,6 @@ namespace Ink_Canvas
LogHelper.WriteLogToFile($"应用媒体元素变换失败: {ex.Message}", LogHelper.LogType.Error);
}
}
}
}