diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index e3c1f7e2..c12148d4 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -3298,6 +3298,9 @@ private void ResetTouchStates() // 清空触摸点计数器 dec.Clear(); + if (isPalmEraserActive) + isPalmEraserActive = false; + // 确保触摸事件能正常响应 inkCanvas.IsHitTestVisible = true; inkCanvas.IsManipulationEnabled = true; diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs index 41415488..4cf59b57 100644 --- a/Ink Canvas/MainWindow_cs/MW_Settings.cs +++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs @@ -3605,6 +3605,11 @@ private void ToggleSwitchEnableMultiTouchMode_Toggled(object sender, RoutedEvent RestoreNonStrokeElements(preservedElements); isInMultiTouchMode = true; + palmEraserWasEnabledBeforeMultiTouch = Settings.Canvas.EnablePalmEraser; + Settings.Canvas.EnablePalmEraser = false; + if (ToggleSwitchEnablePalmEraser != null) + ToggleSwitchEnablePalmEraser.IsOn = false; + // 恢复到之前的编辑状态 inkCanvas.EditingMode = currentEditingMode; drawingShapeMode = currentDrawingShapeMode; @@ -3635,6 +3640,13 @@ private void ToggleSwitchEnableMultiTouchMode_Toggled(object sender, RoutedEvent RestoreNonStrokeElements(preservedElements); isInMultiTouchMode = false; + if (palmEraserWasEnabledBeforeMultiTouch) + { + Settings.Canvas.EnablePalmEraser = true; + if (ToggleSwitchEnablePalmEraser != null) + ToggleSwitchEnablePalmEraser.IsOn = true; + } + // 恢复到之前的编辑状态 inkCanvas.EditingMode = currentEditingMode; drawingShapeMode = currentDrawingShapeMode; diff --git a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs index 48f46d7e..71ec4f8d 100644 --- a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs +++ b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs @@ -44,6 +44,9 @@ public partial class MainWindow : Window /// 多点触控延迟时间(毫秒) /// private const double MULTI_TOUCH_DELAY_MS = 100; + private bool isMultiTouchTimerActive; + private bool isPalmEraserActive; + private bool palmEraserWasEnabledBeforeMultiTouch; /// /// 保存画布上的非笔画元素(如图片、媒体元素等) @@ -227,6 +230,12 @@ private void BorderMultiTouchMode_MouseUp(object sender, MouseButtonEventArgs e) RestoreNonStrokeElements(preservedElements); isInMultiTouchMode = false; + if (palmEraserWasEnabledBeforeMultiTouch) + { + Settings.Canvas.EnablePalmEraser = true; + if (ToggleSwitchEnablePalmEraser != null) + ToggleSwitchEnablePalmEraser.IsOn = true; + } } else { @@ -247,6 +256,11 @@ private void BorderMultiTouchMode_MouseUp(object sender, MouseButtonEventArgs e) // 恢复非笔画元素 RestoreNonStrokeElements(preservedElements); isInMultiTouchMode = true; + + palmEraserWasEnabledBeforeMultiTouch = Settings.Canvas.EnablePalmEraser; + Settings.Canvas.EnablePalmEraser = false; + if (ToggleSwitchEnablePalmEraser != null) + ToggleSwitchEnablePalmEraser.IsOn = false; } } @@ -703,21 +717,13 @@ private void Main_Grid_TouchDown(object sender, TouchEventArgs e) /// 触摸事件参数 /// 返回触摸边界宽度 /// - /// 根据触摸事件参数计算触摸边界宽度,包括以下逻辑: - /// 1. 获取触摸点的边界 - /// 2. 如果不是四边红外屏幕,使用边界宽度 - /// 3. 如果是四边红外屏幕,使用边界宽度和高度的平方根 - /// 4. 如果是特殊屏幕,乘以触摸倍数 - /// 5. 返回计算得到的触摸边界宽度 + /// 手掌擦阈值与特殊屏 TouchMultiplier 在激活逻辑中单独参与计算,此处仅返回几何接触尺寸。 /// public double GetTouchBoundWidth(TouchEventArgs e) { var args = e.GetTouchPoint(null).Bounds; - 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; + if (!Settings.Advanced.IsQuadIR) return args.Width; + return Math.Sqrt(args.Width * args.Height); } /// @@ -741,28 +747,146 @@ public double GetTouchBoundWidth(TouchEventArgs e) /// private void InkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) { + var touchPointForBar = e.GetTouchPoint(this); + var floatingBarBounds = ViewboxFloatingBar.TransformToAncestor(this).TransformBounds( + new Rect(0, 0, ViewboxFloatingBar.ActualWidth, ViewboxFloatingBar.ActualHeight)); + if (floatingBarBounds.Contains(touchPointForBar.Position)) + return; + + if ((inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint + || inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke) + && !isPalmEraserActive) + { + return; + } + + if (drawingShapeMode != 0) + { + inkCanvas.EditingMode = InkCanvasEditingMode.None; + SetCursorBasedOnEditingMode(inkCanvas); + inkCanvas.CaptureTouch(e.TouchDevice); + ViewboxFloatingBar.IsHitTestVisible = false; + BlackboardUIGridForInkReplay.IsHitTestVisible = false; + + isTouchDown = true; + + if (dec.Count == 0) + { + var inkTouchPoint = e.GetTouchPoint(inkCanvas); + if (drawingShapeMode == 24 || drawingShapeMode == 25) + { + if (drawMultiStepShapeCurrentStep == 0) + iniP = inkTouchPoint.Position; + } + else + { + iniP = inkTouchPoint.Position; + } + lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone(); + } + dec.Add(e.TouchDevice.Id); + return; + } + + SetCursorBasedOnEditingMode(inkCanvas); inkCanvas.CaptureTouch(e.TouchDevice); ViewboxFloatingBar.IsHitTestVisible = false; BlackboardUIGridForInkReplay.IsHitTestVisible = false; - + lastTouchDownTime = DateTime.Now; dec.Add(e.TouchDevice.Id); - //设备1个的时候,记录中心点 + + if (Settings.Canvas.EnablePalmEraser && !isPalmEraserActive && drawingShapeMode == 0) + { + var 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) + { + 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; + } + } + } + } + if (dec.Count == 1) { var touchPoint = e.GetTouchPoint(inkCanvas); centerPoint = touchPoint.Position; - - //记录第一根手指点击时的 StrokeCollection lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone(); } - //设备两个及两个以上,将画笔功能关闭 + if (dec.Count > 1 || isSingleFingerDragMode || !Settings.Gesture.IsEnableTwoFingerGesture) { if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return; if (inkCanvas.EditingMode == InkCanvasEditingMode.None || inkCanvas.EditingMode == InkCanvasEditingMode.Select) return; + var timeSinceLastTouch = (DateTime.Now - lastTouchDownTime).TotalMilliseconds; + if (timeSinceLastTouch < MULTI_TOUCH_DELAY_MS && inkCanvas.EditingMode == InkCanvasEditingMode.Ink) + { + if (!isMultiTouchTimerActive) + { + isMultiTouchTimerActive = true; + var remainingTime = MULTI_TOUCH_DELAY_MS - timeSinceLastTouch; + Task.Delay((int)remainingTime).ContinueWith(_ => + { + Dispatcher.Invoke(() => + { + if (dec.Count > 1 && inkCanvas.EditingMode == InkCanvasEditingMode.Ink) + inkCanvas.EditingMode = InkCanvasEditingMode.None; + isMultiTouchTimerActive = false; + }); + }); + } + return; + } + lastInkCanvasEditingMode = inkCanvas.EditingMode; - inkCanvas.EditingMode = InkCanvasEditingMode.None; + if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint + && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke + && drawingShapeMode == 0) + { + inkCanvas.EditingMode = InkCanvasEditingMode.None; + } } } @@ -776,6 +900,11 @@ private void InkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) /// private void InkCanvas_PreviewTouchMove(object sender, TouchEventArgs e) { + if (isPalmEraserActive) + { + var touchPoint = e.GetTouchPoint(inkCanvas); + EraserOverlay_PointerMove(sender, touchPoint.Position); + } } /// @@ -802,32 +931,18 @@ private void InkCanvas_PreviewTouchMove(object sender, TouchEventArgs e) /// private void InkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) { + if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint && !isPalmEraserActive) + { + return; + } inkCanvas.ReleaseAllTouchCaptures(); ViewboxFloatingBar.IsHitTestVisible = true; BlackboardUIGridForInkReplay.IsHitTestVisible = true; - //手势完成后切回之前的状态 - if (dec.Count > 1) - if (inkCanvas.EditingMode == InkCanvasEditingMode.None) - inkCanvas.EditingMode = lastInkCanvasEditingMode; dec.Remove(e.TouchDevice.Id); - if (dec.Count == 0) - { - isSingleFingerDragMode = false; - isWaitUntilNextTouchDown = false; - if (drawingShapeMode == 0 - && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint - && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke - && inkCanvas.EditingMode != InkCanvasEditingMode.Select - && inkCanvas.EditingMode != InkCanvasEditingMode.None) - { - if (lastInkCanvasEditingMode != InkCanvasEditingMode.None) - { - inkCanvas.EditingMode = lastInkCanvasEditingMode; - } - } - } + if (dec.Count <= 1) + isMultiTouchTimerActive = false; if (drawingShapeMode != 0) { @@ -839,12 +954,10 @@ private void InkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) { if (drawMultiStepShapeCurrentStep == 0) { - // 第一笔完成,进入第二笔 drawMultiStepShapeCurrentStep = 1; } else { - // 第二笔完成,完成绘制 var mouseArgs = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) { RoutedEvent = MouseLeftButtonUpEvent, @@ -864,6 +977,36 @@ private void InkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) } } + if (drawingShapeMode == 0) + { + if (dec.Count > 1) + { + if (inkCanvas.EditingMode == InkCanvasEditingMode.None) + { + if (lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint) + inkCanvas.EditingMode = lastInkCanvasEditingMode; + } + } + else if (dec.Count == 0) + { + isSingleFingerDragMode = false; + isWaitUntilNextTouchDown = false; + + if (inkCanvas.EditingMode == InkCanvasEditingMode.None && + lastInkCanvasEditingMode != InkCanvasEditingMode.None && + lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint) + { + inkCanvas.EditingMode = lastInkCanvasEditingMode; + } + + if (isPalmEraserActive) + { + isPalmEraserActive = false; + DisableEraserOverlay(); + } + } + } + inkCanvas.Opacity = 1; if (dec.Count == 0) @@ -961,6 +1104,9 @@ private void Main_Grid_ManipulationCompleted(object sender, ManipulationComplete /// private void Main_Grid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) { + if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) + return; + if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return; bool hasMultipleManipulators = e.Manipulators.Count() >= 2;