From 7095a5890c6ced6f5875997958f2d385689e0d50 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 30 Aug 2025 14:53:50 +0800 Subject: [PATCH] fix:issue #133 --- Ink Canvas/MainWindow.xaml | 15 +- Ink Canvas/MainWindow_cs/MW_Settings.cs | 6 + Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs | 1 + Ink Canvas/MainWindow_cs/MW_TouchEvents.cs | 155 +++++++++++++----- Ink Canvas/Resources/Settings.cs | 2 + 5 files changed, 135 insertions(+), 44 deletions(-) diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index 4013c6ab..1a087381 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -841,7 +841,20 @@ IsOn="False" FontFamily="Microsoft YaHei UI" FontWeight="Bold" Toggled="ToggleSwitchEnablePalmEraser_Toggled" /> - + + + + + + + + + + diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs index 017cc6fd..9d7ca62a 100644 --- a/Ink Canvas/MainWindow_cs/MW_Settings.cs +++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs @@ -3034,6 +3034,12 @@ namespace Ink_Canvas #endregion + private void ComboBoxPalmEraserSensitivity_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (!isLoaded) return; + Settings.Canvas.PalmEraserSensitivity = ComboBoxPalmEraserSensitivity.SelectedIndex; + SaveSettingsToFile(); + } } } diff --git a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs index 439fd7e5..a423b3c2 100644 --- a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs +++ b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs @@ -683,6 +683,7 @@ namespace Ink_Canvas if (Settings.Canvas != null) { ToggleSwitchEnablePalmEraser.IsOn = Settings.Canvas.EnablePalmEraser; + ComboBoxPalmEraserSensitivity.SelectedIndex = Settings.Canvas.PalmEraserSensitivity; } // Advanced diff --git a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs index 92129d26..f3adbf3a 100644 --- a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs +++ b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs @@ -365,8 +365,9 @@ namespace Ink_Canvas private bool palmEraserWasEnabledBeforeMultiTouch; private bool palmEraserTouchDownHandled = false; // 新增:标记手掌擦触摸按下是否已处理 private DateTime palmEraserActivationTime; // 新增:记录手掌擦激活时间 - private const int PALM_ERASER_TIMEOUT_MS = 5000; // 新增:手掌擦超时时间(5秒) + private const int PALM_ERASER_TIMEOUT_MS = 3000; // 修改:减少手掌擦超时时间(3秒) private System.Windows.Threading.DispatcherTimer palmEraserRecoveryTimer; // 新增:手掌擦恢复定时器 + private HashSet palmEraserTouchIds = new HashSet(); // 新增:记录参与手掌擦的触摸点ID private void inkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) { @@ -419,16 +420,57 @@ namespace Ink_Canvas BlackboardUIGridForInkReplay.IsHitTestVisible = false; dec.Add(e.TouchDevice.Id); - // Palm Eraser 逻辑 - 修复:只在触摸按下时处理一次,避免重复触发 + // Palm Eraser 逻辑 - 优化:改进手掌判定条件,提高精度 if (Settings.Canvas.EnablePalmEraser && dec.Count >= 2 && !isPalmEraserActive && !palmEraserTouchDownHandled) { var bounds = e.GetTouchPoint(inkCanvas).Bounds; - double palmThreshold = 40; // 触摸面积阈值,可根据实际调整 - if (bounds.Width >= palmThreshold || bounds.Height >= palmThreshold) + + // 根据敏感度设置调整判定参数 + double palmThreshold; + double aspectRatioThreshold; + int minTouchPoints; + + switch (Settings.Canvas.PalmEraserSensitivity) + { + case 0: // 低敏感度 - 更严格的判定 + palmThreshold = 80; + aspectRatioThreshold = 0.4; + minTouchPoints = 4; + break; + case 1: // 中敏感度 - 平衡的判定 + palmThreshold = 60; + aspectRatioThreshold = 0.3; + minTouchPoints = 3; + break; + case 2: // 高敏感度 - 较宽松的判定 + default: + palmThreshold = 50; + aspectRatioThreshold = 0.25; + minTouchPoints = 2; + break; + } + + // 计算宽高比 + double aspectRatio = Math.Min(bounds.Width, bounds.Height) / Math.Max(bounds.Width, bounds.Height); + + // 更严格的手掌判定条件 + bool isLargeTouch = bounds.Width >= palmThreshold && bounds.Height >= palmThreshold; + bool isPalmLikeShape = aspectRatio >= aspectRatioThreshold; + bool hasMultipleTouchPoints = dec.Count >= minTouchPoints; + + if (isLargeTouch && isPalmLikeShape && hasMultipleTouchPoints) { // 记录当前编辑模式和高光状态 palmEraserLastEditingMode = inkCanvas.EditingMode; palmEraserLastIsHighlighter = drawingAttributes.IsHighlighter; + + // 记录参与手掌擦的触摸点ID + palmEraserTouchIds.Clear(); + foreach (int touchId in dec) + { + palmEraserTouchIds.Add(touchId); + } + // 切换为橡皮擦 EraserIcon_Click(null, null); isPalmEraserActive = true; @@ -437,6 +479,9 @@ namespace Ink_Canvas // 启动恢复定时器,防止卡死 StartPalmEraserRecoveryTimer(); + + // 记录日志 + LogHelper.WriteLogToFile($"Palm eraser activated - Sensitivity: {Settings.Canvas.PalmEraserSensitivity}, Touch bounds: {bounds.Width}x{bounds.Height}, Aspect ratio: {aspectRatio:F2}, Touch points: {dec.Count}", LogHelper.LogType.Info); } } @@ -497,41 +542,54 @@ namespace Ink_Canvas ViewboxFloatingBar.IsHitTestVisible = true; BlackboardUIGridForInkReplay.IsHitTestVisible = true; - // Palm Eraser 逻辑:所有点抬起后恢复原编辑模式 + // Palm Eraser 逻辑:优化状态恢复机制 dec.Remove(e.TouchDevice.Id); - if (isPalmEraserActive && dec.Count == 0) + + // 如果是手掌擦的触摸点,从记录中移除 + if (palmEraserTouchIds.Contains(e.TouchDevice.Id)) + { + palmEraserTouchIds.Remove(e.TouchDevice.Id); + } + + // 当所有手掌擦触摸点都抬起时,恢复原编辑模式 + if (isPalmEraserActive && palmEraserTouchIds.Count == 0) { // 恢复高光状态 drawingAttributes.IsHighlighter = palmEraserLastIsHighlighter; - // 恢复编辑模式 - 修复:确保正确恢复状态 + + // 恢复编辑模式 - 优化:改进状态恢复逻辑 try { if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) { - if (palmEraserLastEditingMode == InkCanvasEditingMode.Ink) + // 根据之前的状态恢复 + switch (palmEraserLastEditingMode) { - PenIcon_Click(null, null); - } - else if (palmEraserLastEditingMode == InkCanvasEditingMode.Select) - { - SymbolIconSelect_MouseUp(null, null); - } - else - { - inkCanvas.EditingMode = 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 recovered to mode: {palmEraserLastEditingMode}", LogHelper.LogType.Info); } } catch (Exception ex) { // 如果恢复失败,强制切换到批注模式 - Trace.WriteLine($"Palm eraser recovery failed: {ex.Message}, forcing to Ink mode"); + LogHelper.WriteLogToFile($"Palm eraser recovery failed: {ex.Message}, forcing to Ink mode", LogHelper.LogType.Error); inkCanvas.EditingMode = InkCanvasEditingMode.Ink; } // 重置手掌擦状态 isPalmEraserActive = false; palmEraserTouchDownHandled = false; + palmEraserTouchIds.Clear(); // 停止恢复定时器 StopPalmEraserRecoveryTimer(); @@ -542,44 +600,47 @@ namespace Ink_Canvas ViewboxFloatingBar.IsHitTestVisible = true; BlackboardUIGridForInkReplay.IsHitTestVisible = true; + + LogHelper.WriteLogToFile("Palm eraser state reset completed", LogHelper.LogType.Info); } // 新增:超时检测 - 如果手掌擦激活时间过长,强制重置状态 - if (isPalmEraserActive && dec.Count == 0) + if (isPalmEraserActive) { var timeSinceActivation = DateTime.Now - palmEraserActivationTime; if (timeSinceActivation.TotalMilliseconds > PALM_ERASER_TIMEOUT_MS) { - Trace.WriteLine($"Palm eraser timeout detected ({timeSinceActivation.TotalMilliseconds}ms), forcing recovery"); + LogHelper.WriteLogToFile($"Palm eraser timeout detected ({timeSinceActivation.TotalMilliseconds}ms), forcing recovery", LogHelper.LogType.Warning); // 强制恢复状态 try { if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) { - if (palmEraserLastEditingMode == InkCanvasEditingMode.Ink) + switch (palmEraserLastEditingMode) { - PenIcon_Click(null, null); - } - else if (palmEraserLastEditingMode == InkCanvasEditingMode.Select) - { - SymbolIconSelect_MouseUp(null, null); - } - else - { - inkCanvas.EditingMode = palmEraserLastEditingMode; + case InkCanvasEditingMode.Ink: + PenIcon_Click(null, null); + break; + case InkCanvasEditingMode.Select: + SymbolIconSelect_MouseUp(null, null); + break; + default: + inkCanvas.EditingMode = palmEraserLastEditingMode; + break; } } } catch (Exception ex) { - Trace.WriteLine($"Palm eraser timeout recovery failed: {ex.Message}, forcing to Ink mode"); + LogHelper.WriteLogToFile($"Palm eraser timeout recovery failed: {ex.Message}, forcing to Ink mode", LogHelper.LogType.Error); inkCanvas.EditingMode = InkCanvasEditingMode.Ink; } // 重置所有手掌擦状态 isPalmEraserActive = false; palmEraserTouchDownHandled = false; + palmEraserTouchIds.Clear(); inkCanvas.IsHitTestVisible = true; inkCanvas.IsManipulationEnabled = true; @@ -588,6 +649,8 @@ namespace Ink_Canvas // 停止恢复定时器 StopPalmEraserRecoveryTimer(); + + LogHelper.WriteLogToFile("Palm eraser timeout recovery completed", LogHelper.LogType.Info); } } // 修复:几何绘制模式下,触摸抬手时应该正确处理,而不是简单模拟鼠标事件 @@ -656,6 +719,7 @@ namespace Ink_Canvas // 如果手掌擦还在激活状态但触摸点已清空,强制重置状态 isPalmEraserActive = false; palmEraserTouchDownHandled = false; + palmEraserTouchIds.Clear(); // 确保清空触摸点ID inkCanvas.IsHitTestVisible = true; inkCanvas.IsManipulationEnabled = true; @@ -902,36 +966,39 @@ namespace Ink_Canvas var timeSinceActivation = DateTime.Now - palmEraserActivationTime; if (timeSinceActivation.TotalMilliseconds > PALM_ERASER_TIMEOUT_MS) { - Trace.WriteLine($"Palm eraser recovery timer triggered, forcing recovery after {timeSinceActivation.TotalMilliseconds}ms"); + LogHelper.WriteLogToFile($"Palm eraser recovery timer triggered, forcing recovery after {timeSinceActivation.TotalMilliseconds}ms", LogHelper.LogType.Warning); // 强制恢复状态 try { if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) { - if (palmEraserLastEditingMode == InkCanvasEditingMode.Ink) + switch (palmEraserLastEditingMode) { - PenIcon_Click(null, null); - } - else if (palmEraserLastEditingMode == InkCanvasEditingMode.Select) - { - SymbolIconSelect_MouseUp(null, null); - } - else - { - inkCanvas.EditingMode = 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 timer recovery to mode: {palmEraserLastEditingMode}", LogHelper.LogType.Info); } } catch (Exception ex) { - Trace.WriteLine($"Palm eraser recovery timer failed: {ex.Message}, forcing to Ink mode"); + LogHelper.WriteLogToFile($"Palm eraser recovery timer failed: {ex.Message}, forcing to Ink mode", LogHelper.LogType.Error); inkCanvas.EditingMode = InkCanvasEditingMode.Ink; } // 重置所有手掌擦状态 isPalmEraserActive = false; palmEraserTouchDownHandled = false; + palmEraserTouchIds.Clear(); inkCanvas.IsHitTestVisible = true; inkCanvas.IsManipulationEnabled = true; @@ -940,6 +1007,8 @@ namespace Ink_Canvas // 停止定时器 StopPalmEraserRecoveryTimer(); + + LogHelper.WriteLogToFile("Palm eraser timer recovery completed", LogHelper.LogType.Info); } } } diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs index 9b8ed589..fc4e687a 100644 --- a/Ink Canvas/Resources/Settings.cs +++ b/Ink Canvas/Resources/Settings.cs @@ -88,6 +88,8 @@ namespace Ink_Canvas public bool IsCompressPicturesUploaded { get; set; } [JsonProperty("enablePalmEraser")] public bool EnablePalmEraser { get; set; } = true; + [JsonProperty("palmEraserSensitivity")] + public int PalmEraserSensitivity { get; set; } = 2; // 0-低敏感度, 1-中敏感度, 2-高敏感度 [JsonProperty("clearCanvasAlsoClearImages")] public bool ClearCanvasAlsoClearImages { get; set; } = true; [JsonProperty("showCircleCenter")]