From c670357c017b3fb410337858b097bb9f4657359b Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 27 Sep 2025 17:01:33 +0800 Subject: [PATCH] =?UTF-8?q?improve:=E6=A9=A1=E7=9A=AE=E6=93=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow.xaml | 20 +- Ink Canvas/MainWindow.xaml.cs | 14 +- Ink Canvas/MainWindow_cs/MW_BoardIcons.cs | 2 +- Ink Canvas/MainWindow_cs/MW_Eraser.cs | 1056 +++++------------ Ink Canvas/MainWindow_cs/MW_Eraser.xaml | 76 +- .../MainWindow_cs/MW_FloatingBarIcons.cs | 17 +- Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs | 5 +- Ink Canvas/MainWindow_cs/MW_TouchEvents.cs | 2 +- 8 files changed, 353 insertions(+), 839 deletions(-) diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index 40dfef3b..3415aded 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -3678,12 +3678,24 @@ SelectionChanged="inkCanvas_SelectionChanged" StrokeCollected="inkCanvas_StrokeCollected" ClipToBounds="False" Background="Transparent" /> - - + Loaded="EraserOverlayCanvas_Loaded" + Panel.ZIndex="1000"> + + + + + + + diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index f981f065..b152bf8e 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -357,23 +357,21 @@ namespace Ink_Canvas if (inkCanvas1.EditingMode == InkCanvasEditingMode.Ink) forcePointEraser = !forcePointEraser; - // 处理高级橡皮擦覆盖层的启用/禁用 - var eraserOverlay = FindName("AdvancedEraserOverlay") as Border; + // 处理橡皮擦覆盖层的启用/禁用 + var eraserOverlay = FindName("EraserOverlayCanvas") as Canvas; if (eraserOverlay != null) { if (inkCanvas1.EditingMode == InkCanvasEditingMode.EraseByPoint) { // 橡皮擦模式下启用覆盖层 - eraserOverlay.IsHitTestVisible = true; - Trace.WriteLine("Advanced Eraser: Overlay enabled in eraser mode"); + EnableEraserOverlay(); + Trace.WriteLine("Eraser: Overlay enabled in eraser mode"); } else { // 其他模式下禁用覆盖层 - eraserOverlay.IsHitTestVisible = false; - // 同时禁用高级橡皮擦系统 - DisableAdvancedEraserSystem(); - Trace.WriteLine("Advanced Eraser: Overlay disabled in non-eraser mode"); + DisableEraserOverlay(); + Trace.WriteLine("Eraser: Overlay disabled in non-eraser mode"); } } } diff --git a/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs b/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs index 4e41ca79..ab4a399e 100644 --- a/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs @@ -716,7 +716,7 @@ namespace Ink_Canvas //} //else { // 禁用高级橡皮擦系统 - DisableAdvancedEraserSystem(); + DisableEraserOverlay(); forceEraser = true; forcePointEraser = false; diff --git a/Ink Canvas/MainWindow_cs/MW_Eraser.cs b/Ink Canvas/MainWindow_cs/MW_Eraser.cs index 7cea34a9..e5d21a04 100644 --- a/Ink Canvas/MainWindow_cs/MW_Eraser.cs +++ b/Ink Canvas/MainWindow_cs/MW_Eraser.cs @@ -12,154 +12,277 @@ namespace Ink_Canvas { public partial class MainWindow : Window { + // 橡皮擦系统核心变量 + public bool isUsingGeometryEraser = false; + private IncrementalStrokeHitTester hitTester = null; - // 新橡皮擦系统的核心变量 - public bool isUsingAdvancedEraser; - private IncrementalStrokeHitTester advancedHitTester; + public double eraserWidth = 64; + public bool isEraserCircleShape = false; + public bool isUsingStrokesEraser = false; - // 橡皮擦配置 - public double currentEraserSize = 64; - public bool isCurrentEraserCircle; - public bool isUsingStrokeEraser; + private Matrix scaleMatrix = new Matrix(); - // 视觉反馈相关 - private Matrix eraserTransformMatrix; - private Point lastEraserPosition; - private bool isEraserVisible; + // 橡皮擦覆盖层相关控件 + private System.Windows.Controls.Canvas eraserOverlayCanvas; + private Image eraserFeedback; + private TranslateTransform eraserFeedbackTranslateTransform; - // 性能优化相关 - private DateTime lastEraserUpdate = DateTime.Now; - private const double ERASER_UPDATE_INTERVAL = 16.67; // 约60FPS - - // 锁定笔画的GUID(如果不存在则创建一个默认值) + // 锁定笔画的GUID private static readonly Guid IsLockGuid = new Guid("12345678-1234-1234-1234-123456789ABC"); - // 橡皮擦视觉反馈控件 - private DrawingVisual eraserVisual = new DrawingVisual(); - private VisualCanvas eraserOverlayCanvas = null; - private Border eraserVisualBorder; // 用于显示橡皮擦视觉反馈的Border - - // 兼容性属性:模拟原有的EraserOverlay_DrawingVisual - private VisualCanvas EraserOverlay_DrawingVisual => eraserOverlayCanvas; - - // 兼容性保持 - [Obsolete("使用 isUsingAdvancedEraser 替代")] - public bool isUsingGeometryEraser - { - get => isUsingAdvancedEraser; - set => isUsingAdvancedEraser = value; - } - - [Obsolete("使用 currentEraserSize 替代")] - public double eraserWidth - { - get => currentEraserSize; - set => currentEraserSize = value; - } - - [Obsolete("使用 isCurrentEraserCircle 替代")] - public bool isEraserCircleShape - { - get => isCurrentEraserCircle; - set => isCurrentEraserCircle = value; - } - - [Obsolete("使用 isUsingStrokeEraser 替代")] - public bool isUsingStrokesEraser - { - get => isUsingStrokeEraser; - set => isUsingStrokeEraser = value; - } - - [Obsolete("使用 eraserTransformMatrix 替代")] - private Matrix scaleMatrix - { - get => eraserTransformMatrix; - set => eraserTransformMatrix = value; - } - /// - /// 新橡皮擦覆盖层加载事件处理 + /// 橡皮擦覆盖层加载事件处理 /// - private void EraserOverlay_Loaded(object sender, RoutedEventArgs e) + private void EraserOverlayCanvas_Loaded(object sender, RoutedEventArgs e) { - var border = (Border)sender; + var canvas = (System.Windows.Controls.Canvas)sender; + eraserOverlayCanvas = canvas; - // 初始化覆盖层 - InitializeEraserOverlay(border); - - Trace.WriteLine("Advanced Eraser: Overlay loaded and initialized"); - } - - /// - /// 开始高级橡皮擦操作 - /// - private void StartAdvancedEraserOperation(object sender) - { - if (isUsingAdvancedEraser) return; - - // 设置操作状态 - isUsingAdvancedEraser = true; - isEraserVisible = true; - - // 更新橡皮擦尺寸 - UpdateEraserSize(); - - // 获取inkCanvas引用 - var inkCanvas = FindName("inkCanvas") as InkCanvas; - if (inkCanvas == null) return; - - // 根据橡皮擦形状创建碰撞检测器 - StylusShape eraserShape = CreateEraserShape(); - advancedHitTester = inkCanvas.Strokes.GetIncrementalStrokeHitTester(eraserShape); - advancedHitTester.StrokeHit += OnAdvancedEraserStrokeHit; - - // 初始化变换矩阵 - InitializeEraserTransform(); - } - - /// - /// 创建橡皮擦形状 - /// - private StylusShape CreateEraserShape() - { - if (isCurrentEraserCircle) + // 获取橡皮擦反馈控件 + eraserFeedback = FindName("EraserFeedback") as Image; + if (eraserFeedback != null) { - return new EllipseStylusShape(currentEraserSize, currentEraserSize); + eraserFeedbackTranslateTransform = eraserFeedback.RenderTransform as TranslateTransform; } - // 矩形橡皮擦,使用与原来相同的逻辑 - return new RectangleStylusShape(currentEraserSize, currentEraserSize / 0.6); + // 绑定事件处理 + canvas.StylusDown += ((o, args) => { + e.Handled = true; + if (args.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) canvas.CaptureStylus(); + EraserOverlay_PointerDown(sender); + }); + canvas.StylusUp += ((o, args) => { + e.Handled = true; + if (args.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) canvas.ReleaseStylusCapture(); + EraserOverlay_PointerUp(sender); + }); + canvas.StylusMove += ((o, args) => { + e.Handled = true; + EraserOverlay_PointerMove(sender, args.GetPosition(inkCanvas)); + }); + canvas.MouseDown += ((o, args) => { + canvas.CaptureMouse(); + EraserOverlay_PointerDown(sender); + }); + canvas.MouseUp += ((o, args) => { + canvas.ReleaseMouseCapture(); + EraserOverlay_PointerUp(sender); + }); + canvas.MouseMove += ((o, args) => { + EraserOverlay_PointerMove(sender, args.GetPosition(inkCanvas)); + }); + + // 设置橡皮擦样式 + UpdateEraserStyle(); } /// - /// 初始化橡皮擦变换矩阵 + /// 更新橡皮擦样式 /// - private void InitializeEraserTransform() + private void UpdateEraserStyle() { - eraserTransformMatrix = new Matrix(); + if (eraserFeedback == null) return; - if (isCurrentEraserCircle) + // 根据橡皮擦形状选择对应的图像资源 + string resourceKey = isEraserCircleShape ? "EllipseEraserImageSource" : "RectangleEraserImageSource"; + var imageSource = TryFindResource(resourceKey) as DrawingImage; + + if (imageSource != null) { - // 圆形橡皮擦:等比例缩放 - var scale = currentEraserSize / 56.0; // 基于56x56的基准尺寸 - eraserTransformMatrix.ScaleAt(scale, scale, 0, 0); + eraserFeedback.Source = imageSource; + } + } + + /// + /// 橡皮擦按下事件处理 + /// + private void EraserOverlay_PointerDown(object sender) + { + if (isUsingGeometryEraser) return; + + // 锁定 + isUsingGeometryEraser = true; + + // 计算高度 + var _h = eraserWidth * 56 / 38; + + // 初始化碰撞检测器 + StylusShape eraserShape; + if (isEraserCircleShape) + { + eraserShape = new EllipseStylusShape(eraserWidth, eraserWidth); } else { - // 矩形橡皮擦:保持传统比例 - var scaleX = currentEraserSize / 38.0; - var scaleY = (currentEraserSize * 56 / 38) / 56.0; - eraserTransformMatrix.ScaleAt(scaleX, scaleY, 0, 0); + eraserShape = new RectangleStylusShape(eraserWidth, _h); + } + + hitTester = inkCanvas.Strokes.GetIncrementalStrokeHitTester(eraserShape); + hitTester.StrokeHit += EraserGeometry_StrokeHit; + + // 计算缩放矩阵 + var scaleX = eraserWidth / 38; + var scaleY = _h / 56; + scaleMatrix = new Matrix(); + scaleMatrix.ScaleAt(scaleX, scaleY, 0, 0); + + // 设置橡皮擦反馈大小 + if (eraserFeedback != null) + { + eraserFeedback.Width = Math.Max(eraserWidth, 10); + eraserFeedback.Height = isEraserCircleShape ? eraserFeedback.Width : _h; + eraserFeedback.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); + eraserFeedback.Visibility = Visibility.Collapsed; + } + } + + /// + /// 橡皮擦抬起事件处理 + /// + private void EraserOverlay_PointerUp(object sender) + { + if (!isUsingGeometryEraser) return; + + // 解锁 + isUsingGeometryEraser = false; + + // 释放捕获 + ((UIElement)sender).ReleaseMouseCapture(); + + // 隐藏橡皮擦反馈 + if (eraserFeedback != null) + { + eraserFeedback.Visibility = Visibility.Collapsed; + } + + // 结束碰撞检测 + if (hitTester != null) + { + hitTester.EndHitTesting(); + hitTester = null; + } + + // 提交橡皮擦历史记录 + if (ReplacedStroke != null || AddedStroke != null) + { + timeMachine.CommitStrokeEraseHistory(ReplacedStroke, AddedStroke); + AddedStroke = null; + ReplacedStroke = null; + } + } + + /// + /// 橡皮擦移动事件处理 + /// + private void EraserOverlay_PointerMove(object sender, Point pt) + { + if (!isUsingGeometryEraser) return; + + if (isUsingStrokesEraser) + { + // 笔画橡皮擦模式 + var _filtered = inkCanvas.Strokes.HitTest(pt).Where(stroke => !stroke.ContainsPropertyData(IsLockGuid)); + var filtered = _filtered as Stroke[] ?? _filtered.ToArray(); + if (!filtered.Any()) return; + inkCanvas.Strokes.Remove(new StrokeCollection(filtered)); + } + else + { + // 几何橡皮擦模式 + // 显示橡皮擦反馈 + if (eraserFeedback != null && eraserFeedback.Visibility == Visibility.Collapsed) + { + eraserFeedback.Visibility = Visibility.Visible; + } + + // 更新橡皮擦位置 + if (eraserFeedbackTranslateTransform != null) + { + eraserFeedbackTranslateTransform.X = pt.X - eraserFeedback.ActualWidth / 2; + eraserFeedbackTranslateTransform.Y = pt.Y - eraserFeedback.ActualHeight / 2; + } + + // 添加点到碰撞检测器 + if (hitTester != null) + { + hitTester.AddPoint(pt); + } + } + } + + /// + /// 橡皮擦几何碰撞事件处理 + /// + private void EraserGeometry_StrokeHit(object sender, StrokeHitEventArgs args) + { + StrokeCollection eraseResult = args.GetPointEraseResults(); + StrokeCollection strokesToReplace = new StrokeCollection { args.HitStroke }; + + // 过滤锁定的笔画 + var filtered_2replace = strokesToReplace.Where(stroke => !stroke.ContainsPropertyData(IsLockGuid)); + var filtered2Replace = filtered_2replace as Stroke[] ?? filtered_2replace.ToArray(); + if (!filtered2Replace.Any()) return; + + var filtered_result = eraseResult.Where(stroke => !stroke.ContainsPropertyData(IsLockGuid)); + var filteredResult = filtered_result as Stroke[] ?? filtered_result.ToArray(); + + // 替换或删除笔画 + if (filteredResult.Any()) + { + inkCanvas.Strokes.Replace(new StrokeCollection(filtered2Replace), new StrokeCollection(filteredResult)); + } + else + { + inkCanvas.Strokes.Remove(new StrokeCollection(filtered2Replace)); + } + } + + /// + /// 启用橡皮擦覆盖层 + /// + public void EnableEraserOverlay() + { + if (eraserOverlayCanvas != null) + { + eraserOverlayCanvas.IsHitTestVisible = true; + eraserOverlayCanvas.Visibility = Visibility.Visible; + } + } + + /// + /// 禁用橡皮擦覆盖层 + /// + public void DisableEraserOverlay() + { + if (eraserOverlayCanvas != null) + { + eraserOverlayCanvas.IsHitTestVisible = false; + eraserOverlayCanvas.Visibility = Visibility.Collapsed; + } + + // 重置橡皮擦状态 + if (isUsingGeometryEraser) + { + isUsingGeometryEraser = false; + if (hitTester != null) + { + hitTester.EndHitTesting(); + hitTester = null; + } + } + + // 隐藏橡皮擦反馈 + if (eraserFeedback != null) + { + eraserFeedback.Visibility = Visibility.Collapsed; } } /// /// 更新橡皮擦尺寸 /// - private void UpdateEraserSize() + public void UpdateEraserSize() { - // 使用与原来相同的逻辑计算橡皮擦尺寸 double k = 1.0; switch (Settings.Canvas.EraserSize) @@ -172,706 +295,83 @@ namespace Ink_Canvas } // 更新形状类型 - isCurrentEraserCircle = (Settings.Canvas.EraserShapeType == 0); + isEraserCircleShape = (Settings.Canvas.EraserShapeType == 0); // 根据形状类型设置尺寸 - if (isCurrentEraserCircle) + if (isEraserCircleShape) { - currentEraserSize = k * 90; // 圆形橡皮擦 - } - else - { - currentEraserSize = k * 90 * 0.6; // 矩形橡皮擦宽度 - } - } - - /// - /// 结束高级橡皮擦操作 - /// - private void EndAdvancedEraserOperation(object sender) - { - if (!isUsingAdvancedEraser) return; - - // 重置操作状态 - isUsingAdvancedEraser = false; - isEraserVisible = false; - - // 释放鼠标捕获 - if (sender is Border border) - { - border.ReleaseMouseCapture(); - } - - // 隐藏橡皮擦视觉反馈 - HideEraserFeedback(); - - // 结束碰撞检测 - if (advancedHitTester != null) - { - advancedHitTester.EndHitTesting(); - advancedHitTester = null; - } - - // 提交橡皮擦历史记录 - CommitEraserHistory(); - } - - /// - /// 隐藏橡皮擦视觉反馈 - /// - private void HideEraserFeedback() - { - try - { - if (eraserVisualBorder != null) - { - eraserVisualBorder.Visibility = Visibility.Collapsed; - } - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error hiding feedback - {ex.Message}"); - } - } - - /// - /// 提交橡皮擦历史记录 - /// - private void CommitEraserHistory() - { - try - { - if (ReplacedStroke != null || AddedStroke != null) - { - timeMachine.CommitStrokeEraseHistory(ReplacedStroke, AddedStroke); - AddedStroke = null; - ReplacedStroke = null; - } - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error committing history - {ex.Message}"); - } - } - - /// - /// 高级橡皮擦笔画碰撞事件处理 - /// - private void OnAdvancedEraserStrokeHit(object sender, StrokeHitEventArgs args) - { - try - { - var inkCanvas = FindName("inkCanvas") as InkCanvas; - if (inkCanvas == null) return; - - var eraseResult = args.GetPointEraseResults(); - var strokeToReplace = new StrokeCollection { args.HitStroke }; - - // 过滤锁定的笔画 - var filteredToReplace = strokeToReplace.Where(stroke => !stroke.ContainsPropertyData(IsLockGuid)); - var filteredToReplaceArray = filteredToReplace as Stroke[] ?? filteredToReplace.ToArray(); - - if (!filteredToReplaceArray.Any()) return; - - var filteredResult = eraseResult.Where(stroke => !stroke.ContainsPropertyData(IsLockGuid)); - var filteredResultArray = filteredResult as Stroke[] ?? filteredResult.ToArray(); - - // 执行笔画替换或删除 - if (filteredResultArray.Any()) - { - inkCanvas.Strokes.Replace( - new StrokeCollection(filteredToReplaceArray), - new StrokeCollection(filteredResultArray) - ); + eraserWidth = k * 90; // 圆形橡皮擦 } else - { - inkCanvas.Strokes.Remove(new StrokeCollection(filteredToReplaceArray)); - } - } - catch (Exception ex) { - Trace.WriteLine($"Advanced Eraser: Error in stroke hit - {ex.Message}"); + eraserWidth = k * 90 * 0.6; // 矩形橡皮擦宽度 } + + // 更新橡皮擦样式 + UpdateEraserStyle(); } /// - /// 更新高级橡皮擦位置 + /// 切换橡皮擦形状 /// - private void UpdateAdvancedEraserPosition(object sender, Point position) + public void ToggleEraserShape() { - // 移除isUsingAdvancedEraser检查,让视觉反馈始终更新 - // if (!isUsingAdvancedEraser) return; - - // 性能优化:限制更新频率 - var now = DateTime.Now; - if ((now - lastEraserUpdate).TotalMilliseconds < ERASER_UPDATE_INTERVAL) - { - return; - } - lastEraserUpdate = now; - - // 更新位置 - lastEraserPosition = position; - - // 更新视觉反馈(始终执行) - UpdateEraserVisualFeedback(position); - - // 只有在实际使用橡皮擦时才处理擦除 - if (isUsingAdvancedEraser) - { - // 处理不同的橡皮擦模式 - if (isUsingStrokeEraser) - { - ProcessStrokeEraserAtPosition(position); - } - else - { - ProcessGeometryEraserAtPosition(position); - } - } + isEraserCircleShape = !isEraserCircleShape; + Settings.Canvas.EraserShapeType = isEraserCircleShape ? 0 : 1; + UpdateEraserStyle(); } /// - /// 在指定位置处理笔画橡皮擦 + /// 切换橡皮擦模式 /// - private void ProcessStrokeEraserAtPosition(Point position) + public void ToggleEraserMode() { - try - { - var inkCanvas = FindName("inkCanvas") as InkCanvas; - if (inkCanvas == null) return; - - var hitStrokes = inkCanvas.Strokes.HitTest(position) - .Where(stroke => !stroke.ContainsPropertyData(IsLockGuid)); - var strokesArray = hitStrokes as Stroke[] ?? hitStrokes.ToArray(); - - if (strokesArray.Any()) - { - inkCanvas.Strokes.Remove(new StrokeCollection(strokesArray)); - } - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error in stroke eraser - {ex.Message}"); - } + isUsingStrokesEraser = !isUsingStrokesEraser; } /// - /// 在指定位置处理几何橡皮擦 - /// - private void ProcessGeometryEraserAtPosition(Point position) - { - try - { - if (advancedHitTester != null) - { - advancedHitTester.AddPoint(position); - } - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error in geometry eraser - {ex.Message}"); - } - } - - /// - /// 更新橡皮擦视觉反馈 - /// - private void UpdateEraserVisualFeedback(Point position) - { - try - { - // 获取或创建橡皮擦视觉反馈Border - if (eraserVisualBorder == null) - { - eraserVisualBorder = new Border - { - Background = new SolidColorBrush(Colors.Transparent), - BorderBrush = new SolidColorBrush(Colors.Transparent), - BorderThickness = new Thickness(0), - IsHitTestVisible = false, - HorizontalAlignment = HorizontalAlignment.Left, - VerticalAlignment = VerticalAlignment.Top, - Opacity = 1 - }; - Panel.SetZIndex(eraserVisualBorder, 1001); - - // 将Border添加到InkCanvasGridForInkReplay中 - var inkCanvasGrid = FindName("InkCanvasGridForInkReplay") as Grid; - if (inkCanvasGrid != null) - { - inkCanvasGrid.Children.Add(eraserVisualBorder); - Trace.WriteLine("Advanced Eraser: Visual feedback border added to grid"); - } - else - { - Trace.WriteLine("Advanced Eraser: Failed to find InkCanvasGridForInkReplay"); - return; // 如果找不到Grid,直接返回 - } - } - - if (eraserVisualBorder != null) - { - // 创建橡皮擦视觉反馈 - var eraserImage = CreateEraserVisualImage(); - - // 清除Border的内容并添加新的图像 - eraserVisualBorder.Child = eraserImage; - - // 更新橡皮擦位置和大小 - if (isCurrentEraserCircle) - { - var radius = currentEraserSize / 2; - eraserVisualBorder.Width = currentEraserSize; - eraserVisualBorder.Height = currentEraserSize; - - // 使用Margin来定位,因为Border在Grid中 - eraserVisualBorder.Margin = new Thickness( - position.X - radius, - position.Y - radius, - 0, 0); - } - else - { - // 矩形橡皮擦,使用与原来相同的逻辑 - var height = currentEraserSize / 0.6; - eraserVisualBorder.Width = currentEraserSize; - eraserVisualBorder.Height = height; - - // 使用Margin来定位,因为Border在Grid中 - eraserVisualBorder.Margin = new Thickness( - position.X - currentEraserSize / 2, - position.Y - height / 2, - 0, 0); - } - - eraserVisualBorder.Visibility = Visibility.Visible; - Trace.WriteLine($"Advanced Eraser: Visual feedback updated to ({position.X:F1}, {position.Y:F1})"); - } - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error updating visual feedback - {ex.Message}"); - } - } - - /// - /// 创建橡皮擦视觉图像 - /// - private Image CreateEraserVisualImage() - { - try - { - // 根据橡皮擦形状选择对应的DrawingGroup资源 - string resourceKey = isCurrentEraserCircle ? "EraserCircleDrawingGroup" : "EraserDrawingGroup"; - - // 尝试从资源字典中获取DrawingGroup - var drawingGroup = TryFindResource(resourceKey) as DrawingGroup; - if (drawingGroup == null) - { - // 如果找不到资源,创建默认的橡皮擦图像 - return CreateDefaultEraserImage(); - } - - // 创建变换后的DrawingGroup - var transformedGroup = new DrawingGroup(); - transformedGroup.Children.Add(drawingGroup); - - // 应用缩放变换 - var transform = new ScaleTransform(); - if (isCurrentEraserCircle) - { - var scale = currentEraserSize / 56.0; // 基于56x56的基准尺寸 - transform.ScaleX = scale; - transform.ScaleY = scale; - } - else - { - var scaleX = currentEraserSize / 38.0; - var scaleY = (currentEraserSize / 0.6) / 56.0; - transform.ScaleX = scaleX; - transform.ScaleY = scaleY; - } - transformedGroup.Transform = transform; - - // 创建DrawingImage - var drawingImage = new DrawingImage(transformedGroup); - - // 创建Image控件 - var image = new Image - { - Source = drawingImage, - Stretch = Stretch.None - }; - RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.HighQuality); - - return image; - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error creating eraser visual image - {ex.Message}"); - return CreateDefaultEraserImage(); - } - } - - /// - /// 创建默认的橡皮擦图像(当资源不可用时) - /// - private Image CreateDefaultEraserImage() - { - try - { - // 创建一个简单的几何图形作为默认橡皮擦 - Geometry geometry; - if (isCurrentEraserCircle) - { - geometry = new EllipseGeometry(new Point(28, 28), 28, 28); - } - else - { - geometry = new RectangleGeometry(new Rect(0, 0, 38, 56)); - } - - var brush = new SolidColorBrush(Colors.LightGray); - var pen = new Pen(new SolidColorBrush(Colors.DarkGray), 1); - - var geometryDrawing = new GeometryDrawing(brush, pen, geometry); - var drawingGroup = new DrawingGroup(); - drawingGroup.Children.Add(geometryDrawing); - - // 应用缩放变换 - var transform = new ScaleTransform(); - if (isCurrentEraserCircle) - { - var scale = currentEraserSize / 56.0; - transform.ScaleX = scale; - transform.ScaleY = scale; - } - else - { - var scaleX = currentEraserSize / 38.0; - var scaleY = (currentEraserSize / 0.6) / 56.0; - transform.ScaleX = scaleX; - transform.ScaleY = scaleY; - } - drawingGroup.Transform = transform; - - var drawingImage = new DrawingImage(drawingGroup); - var image = new Image - { - Source = drawingImage, - Stretch = Stretch.None - }; - - return image; - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error creating default eraser image - {ex.Message}"); - return null; - } - } - - /// - /// 兼容性方法:旧版橡皮擦几何碰撞处理 - /// - [Obsolete("使用 OnAdvancedEraserStrokeHit 替代")] - private void EraserGeometry_StrokeHit(object sender, StrokeHitEventArgs args) - { - OnAdvancedEraserStrokeHit(sender, args); - } - - /// - /// 兼容性方法:旧版橡皮擦移动处理 - /// - [Obsolete("使用 UpdateAdvancedEraserPosition 替代")] - private void EraserOverlay_PointerMove(object sender, Point pt) - { - UpdateAdvancedEraserPosition(sender, pt); - } - - /// - /// 兼容性方法:旧版橡皮擦按下处理 - /// - [Obsolete("使用 StartAdvancedEraserOperation 替代")] - private void EraserOverlay_PointerDown(object sender) - { - StartAdvancedEraserOperation(sender); - } - - /// - /// 兼容性方法:旧版橡皮擦抬起处理 - /// - [Obsolete("使用 EndAdvancedEraserOperation 替代")] - private void EraserOverlay_PointerUp(object sender) - { - EndAdvancedEraserOperation(sender); - } - - /// - /// 获取当前橡皮擦状态信息(用于调试) - /// - public string GetEraserStatusInfo() - { - return "Advanced Eraser Status:\n" + - $"- Active: {isUsingAdvancedEraser}\n" + - $"- Size: {currentEraserSize:F1}\n" + - $"- Shape: {(isCurrentEraserCircle ? "Circle" : "Rectangle")}\n" + - $"- Mode: {(isUsingStrokeEraser ? "Stroke" : "Geometry")}\n" + - $"- Visible: {isEraserVisible}\n" + - $"- Last Position: ({lastEraserPosition.X:F1}, {lastEraserPosition.Y:F1})"; - } - - /// - /// 重置橡皮擦状态 - /// - public void ResetEraserState() - { - isUsingAdvancedEraser = false; - isEraserVisible = false; - lastEraserPosition = new Point(); - - if (advancedHitTester != null) - { - advancedHitTester.EndHitTesting(); - advancedHitTester = null; - } - - HideEraserFeedback(); - - // 清理视觉反馈Border - if (eraserVisualBorder != null) - { - var inkCanvasGrid = FindName("InkCanvasGridForInkReplay") as Grid; - if (inkCanvasGrid != null) - { - inkCanvasGrid.Children.Remove(eraserVisualBorder); - } - eraserVisualBorder = null; - } - } - - /// - /// 应用高级橡皮擦形状到InkCanvas + /// 应用橡皮擦形状到InkCanvas /// public void ApplyAdvancedEraserShape() { try { - var inkCanvas = FindName("inkCanvas") as InkCanvas; - if (inkCanvas == null) return; - - // 更新橡皮擦尺寸和形状 + // 更新橡皮擦尺寸 UpdateEraserSize(); // 创建橡皮擦形状 - StylusShape eraserShape = CreateEraserShape(); + StylusShape eraserShape; + if (isEraserCircleShape) + { + eraserShape = new EllipseStylusShape(eraserWidth, eraserWidth); + } + else + { + var height = eraserWidth * 56 / 38; + eraserShape = new RectangleStylusShape(eraserWidth, height); + } // 应用到InkCanvas inkCanvas.EraserShape = eraserShape; - Trace.WriteLine($"Advanced Eraser: Applied shape - Size: {currentEraserSize}, Circle: {isCurrentEraserCircle}"); + Trace.WriteLine($"Eraser: Applied shape - Size: {eraserWidth}, Circle: {isEraserCircleShape}"); } catch (Exception ex) { - Trace.WriteLine($"Advanced Eraser: Error applying shape - {ex.Message}"); - - // 回退到传统方法 - try - { - ApplyCurrentEraserShape(); - } - catch (Exception fallbackEx) - { - Trace.WriteLine($"Advanced Eraser: Fallback also failed - {fallbackEx.Message}"); - } + Trace.WriteLine($"Eraser: Error applying shape - {ex.Message}"); } } /// - /// 启用高级橡皮擦系统 + /// 获取橡皮擦状态信息 /// - public void EnableAdvancedEraserSystem() + public string GetEraserStatusInfo() { - try - { - // 获取橡皮擦覆盖层 - var eraserOverlay = FindName("AdvancedEraserOverlay") as Border; - if (eraserOverlay != null) - { - // 启用覆盖层的交互 - eraserOverlay.IsHitTestVisible = true; - - // 确保覆盖层在橡皮擦模式下启用 - if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) - { - eraserOverlay.IsHitTestVisible = true; - Trace.WriteLine("Advanced Eraser: Overlay enabled for eraser mode"); - } - - // 设置覆盖层的大小以覆盖整个InkCanvas - var inkCanvasControl = FindName("inkCanvas") as InkCanvas; - if (inkCanvasControl != null) - { - eraserOverlay.Width = inkCanvasControl.ActualWidth; - eraserOverlay.Height = inkCanvasControl.ActualHeight; - Trace.WriteLine($"Advanced Eraser: Overlay size set to {eraserOverlay.Width}x{eraserOverlay.Height}"); - } - - Trace.WriteLine("Advanced Eraser: System enabled successfully"); - } - else - { - Trace.WriteLine("Advanced Eraser: Failed to find eraser overlay"); - } - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error enabling system - {ex.Message}"); - } - } - - /// - /// 初始化橡皮擦覆盖层 - /// - private void InitializeEraserOverlay(Border overlay) - { - try - { - // 设置覆盖层的基本属性 - overlay.Background = new SolidColorBrush(Colors.Transparent); - overlay.IsHitTestVisible = false; // 默认禁用,只在橡皮擦模式下启用 - - // 绑定事件处理 - overlay.MouseDown += (sender, e) => - { - if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) - { - overlay.CaptureMouse(); - StartAdvancedEraserOperation(sender); - - // 处理单点擦除 - var position = e.GetPosition((UIElement)FindName("inkCanvas")); - UpdateAdvancedEraserPosition(sender, position); - } - }; - - overlay.MouseUp += (sender, e) => - { - if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) - { - overlay.ReleaseMouseCapture(); - EndAdvancedEraserOperation(sender); - } - }; - - overlay.MouseMove += (sender, e) => - { - if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) - { - var position = e.GetPosition((UIElement)FindName("inkCanvas")); - Trace.WriteLine($"Advanced Eraser: Mouse move event triggered at ({position.X:F1}, {position.Y:F1})"); - UpdateAdvancedEraserPosition(sender, position); - } - else - { - Trace.WriteLine($"Advanced Eraser: Mouse move ignored - not in eraser mode, current mode: {inkCanvas.EditingMode}"); - } - }; - - // 触控笔事件 - overlay.StylusDown += (sender, e) => - { - if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) - { - e.Handled = true; - if (e.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) - { - overlay.CaptureStylus(); - } - StartAdvancedEraserOperation(sender); - - // 处理单点擦除 - var position = e.GetPosition((UIElement)FindName("inkCanvas")); - UpdateAdvancedEraserPosition(sender, position); - } - }; - - overlay.StylusUp += (sender, e) => - { - if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) - { - e.Handled = true; - if (e.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) - { - overlay.ReleaseStylusCapture(); - } - EndAdvancedEraserOperation(sender); - } - }; - - overlay.StylusMove += (sender, e) => - { - if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) - { - e.Handled = true; - var position = e.GetPosition((UIElement)FindName("inkCanvas")); - UpdateAdvancedEraserPosition(sender, position); - Trace.WriteLine($"Advanced Eraser: Stylus move at ({position.X:F1}, {position.Y:F1})"); - } - }; - - Trace.WriteLine("Advanced Eraser: Overlay initialized successfully"); - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error initializing overlay - {ex.Message}"); - } - } - - /// - /// 禁用高级橡皮擦系统 - /// - public void DisableAdvancedEraserSystem() - { - try - { - // 重置橡皮擦状态 - ResetEraserState(); - - // 获取橡皮擦覆盖层并禁用 - var eraserOverlay = FindName("AdvancedEraserOverlay") as Border; - if (eraserOverlay != null) - { - eraserOverlay.IsHitTestVisible = false; - } - - // 确保视觉反馈被隐藏 - HideEraserFeedback(); - - Trace.WriteLine("Advanced Eraser: System disabled successfully"); - } - catch (Exception ex) - { - Trace.WriteLine($"Advanced Eraser: Error disabling system - {ex.Message}"); - } - } - - /// - /// 切换橡皮擦形状(圆形/矩形) - /// - public void ToggleEraserShape() - { - isCurrentEraserCircle = !isCurrentEraserCircle; - - // 更新设置 - Settings.Canvas.EraserShapeType = isCurrentEraserCircle ? 0 : 1; - - // 应用新形状 - ApplyAdvancedEraserShape(); - - Trace.WriteLine($"Advanced Eraser: Toggled to {(isCurrentEraserCircle ? "Circle" : "Rectangle")}"); + return $"橡皮擦状态:\n" + + $"- 激活: {isUsingGeometryEraser}\n" + + $"- 尺寸: {eraserWidth:F1}\n" + + $"- 形状: {(isEraserCircleShape ? "圆形" : "矩形")}\n" + + $"- 模式: {(isUsingStrokesEraser ? "笔画" : "几何")}"; } } -} +} \ No newline at end of file diff --git a/Ink Canvas/MainWindow_cs/MW_Eraser.xaml b/Ink Canvas/MainWindow_cs/MW_Eraser.xaml index f6cdf56e..f12f83ba 100644 --- a/Ink Canvas/MainWindow_cs/MW_Eraser.xaml +++ b/Ink Canvas/MainWindow_cs/MW_Eraser.xaml @@ -1,36 +1,46 @@  - - - - - - - - - - - - - - - - + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index ef34fd13..24d3353e 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -1867,7 +1867,7 @@ namespace Ink_Canvas if (sender == Cursor_Icon && lastBorderMouseDownObject != Cursor_Icon) return; // 禁用高级橡皮擦系统 - DisableAdvancedEraserSystem(); + DisableEraserOverlay(); // 使用集中化的工具模式切换方法,确保快捷键状态正确更新 // 鼠标模式下应该禁用快捷键以放行键盘操作 @@ -1988,7 +1988,7 @@ namespace Ink_Canvas } // 禁用高级橡皮擦系统 - DisableAdvancedEraserSystem(); + DisableEraserOverlay(); ExitMultiTouchModeIfNeeded(); @@ -2240,7 +2240,7 @@ namespace Ink_Canvas } // 启用新的高级橡皮擦系统 - EnableAdvancedEraserSystem(); + EnableEraserOverlay(); // 使用新的高级橡皮擦系统 // 使用集中化的工具模式切换方法 @@ -2252,10 +2252,7 @@ namespace Ink_Canvas ApplyAdvancedEraserShape(); // 使用新的橡皮擦形状应用方法 SetCursorBasedOnEditingMode(inkCanvas); HideSubPanels("eraser"); // 高亮橡皮按钮 - - // 显示橡皮擦视觉反馈(用于测试) - // 注意:eraserVisualBorder在MW_Eraser.cs中定义,这里无法直接访问 - Trace.WriteLine($"Advanced Eraser: Eraser button clicked, current size: {currentEraserSize}, circle: {isCurrentEraserCircle}"); + Trace.WriteLine($"Eraser: Eraser button clicked, current size: {eraserWidth}, circle: {isEraserCircleShape}"); if (isAlreadyEraser) { @@ -2284,7 +2281,7 @@ namespace Ink_Canvas drawingShapeMode = 0; // 启用新的高级橡皮擦系统 - EnableAdvancedEraserSystem(); + EnableEraserOverlay(); // 使用新的高级橡皮擦系统 // 使用集中化的工具模式切换方法 @@ -2323,7 +2320,7 @@ namespace Ink_Canvas if (sender == EraserByStrokes_Icon && lastBorderMouseDownObject != EraserByStrokes_Icon) return; // 禁用高级橡皮擦系统 - DisableAdvancedEraserSystem(); + DisableEraserOverlay(); forceEraser = true; forcePointEraser = false; @@ -2600,7 +2597,7 @@ namespace Ink_Canvas private void SelectIcon_MouseUp(object sender, RoutedEventArgs e) { // 禁用高级橡皮擦系统 - DisableAdvancedEraserSystem(); + DisableEraserOverlay(); forceEraser = true; drawingShapeMode = 0; diff --git a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs index 922111de..b2840d8a 100644 --- a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs +++ b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs @@ -127,10 +127,7 @@ namespace Ink_Canvas } // 禁用高级橡皮擦系统 - DisableAdvancedEraserSystem(); - - // 修复:从橡皮擦切换到批注模式时,退出多指书写模式 - // 这解决了从橡皮擦切换为批注时被锁定为多指书写的问题 + DisableEraserOverlay(); ExitMultiTouchModeIfNeeded(); // 如果当前已是批注模式,再次点击弹出批注子面板 diff --git a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs index 117a598a..126581d5 100644 --- a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs +++ b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs @@ -45,7 +45,7 @@ namespace Ink_Canvas // 保存图片、媒体元素等非笔画相关的UI元素 if (child is Image || child is MediaElement || - (child is Border border && border.Name != "AdvancedEraserOverlay")) + (child is Border border && border.Name != "EraserOverlayCanvas")) { // 创建元素的深拷贝,避免直接引用导致的问题 var clonedElement = CloneUIElement(child);