Files

155 lines
6.0 KiB
C#
Raw Permalink Normal View History

2025-08-23 21:39:21 +08:00
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using Ink_Canvas.Helpers;
namespace Ink_Canvas {
public partial class MainWindow : PerformanceTransparentWin {
public bool isUsingGeometryEraser = false;
private IncrementalStrokeHitTester hitTester = null;
public double eraserWidth = 64;
public bool isEraserCircleShape = false;
public bool isUsingStrokesEraser = false;
private Matrix scaleMatrix = new Matrix();
private void EraserOverlay_Loaded(object sender, RoutedEventArgs e) {
var bd = (Border)sender;
bd.StylusDown += ((o, args) => {
e.Handled = true;
if (args.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) ((Border)o).CaptureStylus();
EraserOverlay_PointerDown(sender);
});
bd.StylusUp += ((o, args) => {
e.Handled = true;
if (args.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) ((Border)o).ReleaseStylusCapture();
EraserOverlay_PointerUp(sender);
});
bd.StylusMove += ((o, args) => {
e.Handled = true;
EraserOverlay_PointerMove(sender, args.GetPosition(Main_Grid));
});
bd.MouseDown += ((o, args) => {
((Border)o).CaptureMouse();
EraserOverlay_PointerDown(sender);
});
bd.MouseUp += ((o, args) => {
((Border)o).ReleaseMouseCapture();
EraserOverlay_PointerUp(sender);
});
bd.MouseMove += ((o, args) => {
EraserOverlay_PointerMove(sender, args.GetPosition(Main_Grid));
});
bd.StylusButtonUp += (o, args) => {
Trace.WriteLine("ButtonUp!!!!!");
};
}
private void EraserOverlay_PointerDown(object sender) {
if (isUsingGeometryEraser) return;
// lock
isUsingGeometryEraser = true;
// caculate height
var _h = eraserWidth * 56 / 38;
// init hittester
hitTester = inkCanvas.Strokes.GetIncrementalStrokeHitTester(new RectangleStylusShape(
eraserWidth, _h));
hitTester.StrokeHit += EraserGeometry_StrokeHit;
// eraser bitmap cache
EraserOverlay_DrawingVisual.CacheMode = new BitmapCache();
// caculate scale matrix
var scaleX = eraserWidth / 38;
var scaleY = _h / 56;
scaleMatrix = new Matrix();
scaleMatrix.ScaleAt(scaleX,scaleY,0,0);
}
private void EraserOverlay_PointerUp(object sender) {
if (!isUsingGeometryEraser) return;
// unlock
isUsingGeometryEraser = false;
// release capture
((Border)sender).ReleaseMouseCapture();
// hide eraser feedback
var ct = EraserOverlay_DrawingVisual.DrawingVisual.RenderOpen();
ct.DrawRectangle(new SolidColorBrush(Colors.Transparent),null,new Rect(0,0,ActualWidth,ActualHeight));
ct.Close();
// end hittest
hitTester.EndHitTesting();
// commit stroke erased history
// 我有受虐倾向,被这个bug硬控10秒钟,请大家嘲笑我
if (ReplacedStroke != null || AddedStroke != null) {
timeMachine.CommitStrokeEraseHistory(ReplacedStroke, AddedStroke);
AddedStroke = null;
ReplacedStroke = null;
}
}
private void EraserGeometry_StrokeHit(object sender,
StrokeHitEventArgs args) {
StrokeCollection eraseResult =
args.GetPointEraseResults();
StrokeCollection strokesToReplace = new StrokeCollection {
args.HitStroke
};
// replace the old stroke with the new one.
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));
}
}
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 {
// draw eraser feedback
var ct = EraserOverlay_DrawingVisual.DrawingVisual.RenderOpen();
var mt = scaleMatrix;
var _h = eraserWidth * 56 / 38;
mt.Translate(pt.X - eraserWidth / 2, pt.Y - _h / 2);
ct.PushTransform(new MatrixTransform(mt));
ct.DrawDrawing(FindResource(isEraserCircleShape?"EraserCircleDrawingGroup":"EraserDrawingGroup") as DrawingGroup);
ct.Pop();
ct.Close();
// add point to hittester
hitTester.AddPoint(pt);
}
}
}
}