InkCanvasForClass/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs

421 lines
19 KiB
C#
Raw Normal View History

2024-05-01 18:23:32 +08:00
using Ink_Canvas.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
2024-05-01 18:23:32 +08:00
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using Point = System.Windows.Point;
2024-06-05 20:25:26 +08:00
namespace Ink_Canvas {
public partial class MainWindow : Window {
2024-05-01 18:23:32 +08:00
#region Multi-Touch
2024-06-05 20:25:26 +08:00
private bool isInMultiTouchMode = false;
private void BorderMultiTouchMode_MouseUp(object sender, MouseButtonEventArgs e) {
if (isInMultiTouchMode) {
2024-05-01 18:23:32 +08:00
inkCanvas.StylusDown -= MainWindow_StylusDown;
inkCanvas.StylusMove -= MainWindow_StylusMove;
inkCanvas.StylusUp -= MainWindow_StylusUp;
inkCanvas.TouchDown -= MainWindow_TouchDown;
inkCanvas.TouchDown += Main_Grid_TouchDown;
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
inkCanvas.Children.Clear();
isInMultiTouchMode = false;
}
2024-06-05 20:25:26 +08:00
else {
2024-05-01 18:23:32 +08:00
inkCanvas.StylusDown += MainWindow_StylusDown;
inkCanvas.StylusMove += MainWindow_StylusMove;
inkCanvas.StylusUp += MainWindow_StylusUp;
inkCanvas.TouchDown += MainWindow_TouchDown;
inkCanvas.TouchDown -= Main_Grid_TouchDown;
inkCanvas.EditingMode = InkCanvasEditingMode.None;
2024-05-01 18:23:32 +08:00
inkCanvas.Children.Clear();
isInMultiTouchMode = true;
}
}
2024-06-05 20:25:26 +08:00
private void MainWindow_TouchDown(object sender, TouchEventArgs e) {
2024-05-02 02:05:33 +08:00
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint
|| inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke
|| inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
2024-06-05 20:25:26 +08:00
if (!isHidingSubPanelsWhenInking) {
2024-05-01 18:23:32 +08:00
isHidingSubPanelsWhenInking = true;
HideSubPanels(); // 书写时自动隐藏二级菜单
}
double boundWidth = e.GetTouchPoint(null).Bounds.Width, eraserMultiplier = 1.0;
if (!Settings.Advanced.EraserBindTouchMultiplier && Settings.Advanced.IsSpecialScreen)
eraserMultiplier = 1 / Settings.Advanced.TouchMultiplier;
if ((Settings.Advanced.TouchMultiplier != 0 || !Settings.Advanced.IsSpecialScreen) //启用特殊屏幕且触摸倍数为 0 时禁用橡皮
2024-06-05 20:25:26 +08:00
&& boundWidth > BoundsWidth * 2.5) {
if (drawingShapeMode == 0 && forceEraser) return;
double k = 1;
2024-06-05 20:25:26 +08:00
switch (Settings.Canvas.EraserSize) {
case 0:
k = 0.5;
break;
case 1:
k = 0.8;
break;
case 3:
k = 1.25;
break;
case 4:
k = 1.8;
break;
}
2024-06-05 20:25:26 +08:00
inkCanvas.EraserShape = new EllipseStylusShape(boundWidth * k * eraserMultiplier * 0.25,
boundWidth * k * eraserMultiplier * 0.25);
2024-05-01 18:23:32 +08:00
TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.EraseByPoint;
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
}
2024-06-05 20:25:26 +08:00
else {
TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.None;
inkCanvas.EditingMode = InkCanvasEditingMode.None;
2024-05-01 18:23:32 +08:00
}
}
2024-06-05 20:25:26 +08:00
private void MainWindow_StylusDown(object sender, StylusDownEventArgs e) {
2024-05-02 02:05:33 +08:00
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint
|| inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke
|| inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
TouchDownPointsList[e.StylusDevice.Id] = InkCanvasEditingMode.None;
2024-05-01 18:23:32 +08:00
}
2024-06-05 20:25:26 +08:00
private async void MainWindow_StylusUp(object sender, StylusEventArgs e) {
try {
2024-05-01 18:23:32 +08:00
inkCanvas.Strokes.Add(GetStrokeVisual(e.StylusDevice.Id).Stroke);
await Task.Delay(5); // 避免渲染墨迹完成前预览墨迹被删除导致墨迹闪烁
2024-05-01 18:23:32 +08:00
inkCanvas.Children.Remove(GetVisualCanvas(e.StylusDevice.Id));
2024-06-05 20:25:26 +08:00
inkCanvas_StrokeCollected(inkCanvas,
new InkCanvasStrokeCollectedEventArgs(GetStrokeVisual(e.StylusDevice.Id).Stroke));
}
2024-06-05 20:25:26 +08:00
catch (Exception ex) {
2024-05-01 18:23:32 +08:00
Label.Content = ex.ToString();
}
2024-06-05 20:25:26 +08:00
try {
2024-05-01 18:23:32 +08:00
StrokeVisualList.Remove(e.StylusDevice.Id);
VisualCanvasList.Remove(e.StylusDevice.Id);
TouchDownPointsList.Remove(e.StylusDevice.Id);
2024-06-05 20:25:26 +08:00
if (StrokeVisualList.Count == 0 || VisualCanvasList.Count == 0 || TouchDownPointsList.Count == 0) {
2024-05-01 18:23:32 +08:00
inkCanvas.Children.Clear();
StrokeVisualList.Clear();
VisualCanvasList.Clear();
TouchDownPointsList.Clear();
}
}
catch { }
2024-05-01 18:23:32 +08:00
}
2024-06-05 20:25:26 +08:00
private void MainWindow_StylusMove(object sender, StylusEventArgs e) {
try {
if (GetTouchDownPointsList(e.StylusDevice.Id) != InkCanvasEditingMode.None) return;
2024-06-05 20:25:26 +08:00
try {
2024-05-01 18:23:32 +08:00
if (e.StylusDevice.StylusButtons[1].StylusButtonState == StylusButtonState.Down) return;
}
catch { }
2024-06-05 20:25:26 +08:00
2024-05-01 18:23:32 +08:00
var strokeVisual = GetStrokeVisual(e.StylusDevice.Id);
var stylusPointCollection = e.GetStylusPoints(this);
foreach (var stylusPoint in stylusPointCollection)
2024-05-01 18:23:32 +08:00
strokeVisual.Add(new StylusPoint(stylusPoint.X, stylusPoint.Y, stylusPoint.PressureFactor));
strokeVisual.Redraw();
}
catch { }
2024-05-01 18:23:32 +08:00
}
2024-06-05 20:25:26 +08:00
private StrokeVisual GetStrokeVisual(int id) {
if (StrokeVisualList.TryGetValue(id, out var visual)) return visual;
2024-05-01 18:23:32 +08:00
var strokeVisual = new StrokeVisual(inkCanvas.DefaultDrawingAttributes.Clone());
StrokeVisualList[id] = strokeVisual;
StrokeVisualList[id] = strokeVisual;
var visualCanvas = new VisualCanvas(strokeVisual);
VisualCanvasList[id] = visualCanvas;
inkCanvas.Children.Add(visualCanvas);
return strokeVisual;
}
2024-06-05 20:25:26 +08:00
private VisualCanvas GetVisualCanvas(int id) {
return VisualCanvasList.TryGetValue(id, out var visualCanvas) ? visualCanvas : null;
2024-05-01 18:23:32 +08:00
}
2024-06-05 20:25:26 +08:00
private InkCanvasEditingMode GetTouchDownPointsList(int id) {
return TouchDownPointsList.TryGetValue(id, out var inkCanvasEditingMode) ? inkCanvasEditingMode : inkCanvas.EditingMode;
2024-05-01 18:23:32 +08:00
}
2024-06-05 20:25:26 +08:00
private Dictionary<int, InkCanvasEditingMode> TouchDownPointsList { get; } =
new Dictionary<int, InkCanvasEditingMode>();
2024-05-01 18:23:32 +08:00
private Dictionary<int, StrokeVisual> StrokeVisualList { get; } = new Dictionary<int, StrokeVisual>();
private Dictionary<int, VisualCanvas> VisualCanvasList { get; } = new Dictionary<int, VisualCanvas>();
#endregion
2024-06-05 20:25:26 +08:00
private int lastTouchDownTime = 0, lastTouchUpTime = 0;
2024-06-05 20:25:26 +08:00
private Point iniP = new Point(0, 0);
private bool isLastTouchEraser = false;
2024-05-01 18:23:32 +08:00
private bool forcePointEraser = true;
2024-06-05 20:25:26 +08:00
private void Main_Grid_TouchDown(object sender, TouchEventArgs e) {
if (!isHidingSubPanelsWhenInking) {
2024-05-01 18:23:32 +08:00
isHidingSubPanelsWhenInking = true;
HideSubPanels(); // 书写时自动隐藏二级菜单
}
2024-06-05 20:25:26 +08:00
if (NeedUpdateIniP()) iniP = e.GetTouchPoint(inkCanvas).Position;
if (drawingShapeMode == 9 && isFirstTouchCuboid == false) MouseTouchMove(iniP);
2024-05-01 18:23:32 +08:00
inkCanvas.Opacity = 1;
double boundsWidth = GetTouchBoundWidth(e), eraserMultiplier = 1.0;
if (!Settings.Advanced.EraserBindTouchMultiplier && Settings.Advanced.IsSpecialScreen)
eraserMultiplier = 1 / Settings.Advanced.TouchMultiplier;
2024-06-05 20:25:26 +08:00
if (boundsWidth > BoundsWidth) {
2024-05-01 18:23:32 +08:00
isLastTouchEraser = true;
if (drawingShapeMode == 0 && forceEraser) return;
2024-06-05 20:25:26 +08:00
if (boundsWidth > BoundsWidth * 2.5) {
2024-05-01 18:23:32 +08:00
double k = 1;
2024-06-05 20:25:26 +08:00
switch (Settings.Canvas.EraserSize) {
2024-05-01 18:23:32 +08:00
case 0:
k = 0.5;
break;
case 1:
k = 0.8;
break;
case 3:
k = 1.25;
break;
case 4:
k = 1.8;
break;
}
2024-06-05 20:25:26 +08:00
inkCanvas.EraserShape = new EllipseStylusShape(boundsWidth * k * eraserMultiplier,
boundsWidth * k * eraserMultiplier);
2024-05-01 18:23:32 +08:00
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
}
2024-06-05 20:25:26 +08:00
else {
if (StackPanelPPTControls.Visibility == Visibility.Visible && inkCanvas.Strokes.Count == 0 &&
Settings.PowerPointSettings.IsEnableFingerGestureSlideShowControl) {
2024-05-01 18:23:32 +08:00
isLastTouchEraser = false;
inkCanvas.EditingMode = InkCanvasEditingMode.GestureOnly;
inkCanvas.Opacity = 0.1;
}
2024-06-05 20:25:26 +08:00
else {
2024-05-01 18:23:32 +08:00
inkCanvas.EraserShape = new EllipseStylusShape(5, 5);
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
}
}
}
2024-06-05 20:25:26 +08:00
else {
2024-05-01 18:23:32 +08:00
isLastTouchEraser = false;
2024-06-05 20:25:26 +08:00
inkCanvas.EraserShape =
forcePointEraser ? new EllipseStylusShape(50, 50) : new EllipseStylusShape(5, 5);
2024-05-01 18:23:32 +08:00
if (forceEraser) return;
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
}
}
2024-06-05 20:25:26 +08:00
private double GetTouchBoundWidth(TouchEventArgs e) {
2024-05-01 18:23:32 +08:00
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;
}
//记录触摸设备ID
private List<int> dec = new List<int>();
2024-06-05 20:25:26 +08:00
2024-05-01 18:23:32 +08:00
//中心点
2024-06-05 20:25:26 +08:00
private Point centerPoint;
private InkCanvasEditingMode lastInkCanvasEditingMode = InkCanvasEditingMode.Ink;
private bool isSingleFingerDragMode = false;
2024-05-01 18:23:32 +08:00
2024-06-05 20:25:26 +08:00
private void inkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) {
2024-05-01 18:23:32 +08:00
dec.Add(e.TouchDevice.Id);
//设备1个的时候记录中心点
2024-06-05 20:25:26 +08:00
if (dec.Count == 1) {
var touchPoint = e.GetTouchPoint(inkCanvas);
2024-05-01 18:23:32 +08:00
centerPoint = touchPoint.Position;
//记录第一根手指点击时的 StrokeCollection
lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone();
}
2024-06-05 20:25:26 +08:00
2024-05-01 18:23:32 +08:00
//设备两个及两个以上,将画笔功能关闭
2024-06-05 20:25:26 +08:00
if (dec.Count > 1 || isSingleFingerDragMode || !Settings.Gesture.IsEnableTwoFingerGesture) {
2024-05-01 18:23:32 +08:00
if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return;
2024-06-05 20:25:26 +08:00
if (inkCanvas.EditingMode == InkCanvasEditingMode.None ||
inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
lastInkCanvasEditingMode = inkCanvas.EditingMode;
inkCanvas.EditingMode = InkCanvasEditingMode.None;
2024-05-01 18:23:32 +08:00
}
}
2024-06-05 20:25:26 +08:00
private void inkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) {
2024-05-01 18:23:32 +08:00
//手势完成后切回之前的状态
if (dec.Count > 1)
if (inkCanvas.EditingMode == InkCanvasEditingMode.None)
2024-05-01 18:23:32 +08:00
inkCanvas.EditingMode = lastInkCanvasEditingMode;
dec.Remove(e.TouchDevice.Id);
inkCanvas.Opacity = 1;
if (dec.Count == 0)
2024-05-01 18:23:32 +08:00
if (lastTouchDownStrokeCollection.Count() != inkCanvas.Strokes.Count() &&
2024-06-05 20:25:26 +08:00
!(drawingShapeMode == 9 && !isFirstTouchCuboid)) {
var whiteboardIndex = CurrentWhiteboardIndex;
if (currentMode == 0) whiteboardIndex = 0;
2024-05-01 18:23:32 +08:00
strokeCollections[whiteboardIndex] = lastTouchDownStrokeCollection;
}
}
2024-06-05 20:25:26 +08:00
private void inkCanvas_ManipulationStarting(object sender, ManipulationStartingEventArgs e) {
2024-05-01 18:23:32 +08:00
e.Mode = ManipulationModes.All;
}
2024-06-05 20:25:26 +08:00
private void inkCanvas_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e) { }
2024-05-01 18:23:32 +08:00
2024-06-05 20:25:26 +08:00
private void Main_Grid_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) {
if (e.Manipulators.Count() != 0) return;
if (forceEraser) return;
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
2024-05-01 18:23:32 +08:00
}
// -- removed --
//
//private void inkCanvas_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
//{
// if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture || inkCanvas.Strokes.Count == 0 || dec.Count() < 2) return;
// _currentCommitType = CommitReason.Manipulation;
// StrokeCollection strokes = inkCanvas.GetSelectedStrokes();
// if (strokes.Count != 0)
// {
// inkCanvas.Strokes.Replace(strokes, strokes.Clone());
// }
// else
// {
// var originalStrokes = inkCanvas.Strokes;
// var targetStrokes = originalStrokes.Clone();
// originalStrokes.Replace(originalStrokes, targetStrokes);
// }
// _currentCommitType = CommitReason.UserInput;
//}
2024-06-05 20:25:26 +08:00
private void Main_Grid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) {
2024-05-01 18:23:32 +08:00
if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return;
2024-06-05 20:25:26 +08:00
if ((dec.Count >= 2 && (Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode ||
StackPanelPPTControls.Visibility != Visibility.Visible ||
StackPanelPPTButtons.Visibility == Visibility.Collapsed)) ||
isSingleFingerDragMode) {
var md = e.DeltaManipulation;
var trans = md.Translation; // 获得位移矢量
2024-05-01 18:23:32 +08:00
2024-06-05 20:25:26 +08:00
var m = new Matrix();
2024-05-01 18:23:32 +08:00
if (Settings.Gesture.IsEnableTwoFingerTranslate)
2024-06-05 20:25:26 +08:00
m.Translate(trans.X, trans.Y); // 移动
2024-05-01 18:23:32 +08:00
2024-06-05 20:25:26 +08:00
if (Settings.Gesture.IsEnableTwoFingerGestureTranslateOrRotation) {
var rotate = md.Rotation; // 获得旋转角度
var scale = md.Scale; // 获得缩放倍数
2024-05-01 18:23:32 +08:00
// Find center of element and then transform to get current location of center
2024-06-05 20:25:26 +08:00
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
2024-05-01 18:23:32 +08:00
if (Settings.Gesture.IsEnableTwoFingerRotation)
2024-06-05 20:25:26 +08:00
m.RotateAt(rotate, center.X, center.Y); // 旋转
2024-05-01 18:23:32 +08:00
if (Settings.Gesture.IsEnableTwoFingerZoom)
2024-06-05 20:25:26 +08:00
m.ScaleAt(scale.X, scale.Y, center.X, center.Y); // 缩放
2024-05-01 18:23:32 +08:00
}
2024-06-05 20:25:26 +08:00
var strokes = inkCanvas.GetSelectedStrokes();
if (strokes.Count != 0) {
foreach (var stroke in strokes) {
2024-05-01 18:23:32 +08:00
stroke.Transform(m, false);
2024-06-05 20:25:26 +08:00
foreach (var circle in circles)
if (stroke == circle.Stroke) {
circle.R = GetDistance(circle.Stroke.StylusPoints[0].ToPoint(),
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].ToPoint()) / 2;
circle.Centroid = new Point(
(circle.Stroke.StylusPoints[0].X +
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].X) / 2,
(circle.Stroke.StylusPoints[0].Y +
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].Y) / 2);
2024-05-01 18:23:32 +08:00
break;
}
2024-06-05 20:25:26 +08:00
if (!Settings.Gesture.IsEnableTwoFingerZoom) continue;
try {
stroke.DrawingAttributes.Width *= md.Scale.X;
stroke.DrawingAttributes.Height *= md.Scale.Y;
2024-05-01 18:23:32 +08:00
}
2024-06-05 20:25:26 +08:00
catch { }
2024-05-01 18:23:32 +08:00
}
2024-06-05 20:25:26 +08:00
if (lastTempManiputlaionMatrix == null) {
lastTempManiputlaionMatrix = m;
lastTempStrokeCollection = strokes;
}
2024-06-05 20:25:26 +08:00
else {
lastTempManiputlaionMatrix?.Append(m);
}
}
2024-06-05 20:25:26 +08:00
else {
if (Settings.Gesture.IsEnableTwoFingerZoom) {
foreach (var stroke in inkCanvas.Strokes) {
2024-05-01 18:23:32 +08:00
stroke.Transform(m, false);
2024-06-05 20:25:26 +08:00
try {
2024-05-01 18:23:32 +08:00
stroke.DrawingAttributes.Width *= md.Scale.X;
stroke.DrawingAttributes.Height *= md.Scale.Y;
}
catch { }
2024-06-05 20:25:26 +08:00
}
;
}
2024-06-05 20:25:26 +08:00
else {
foreach (var stroke in inkCanvas.Strokes) stroke.Transform(m, false);
;
2024-05-01 18:23:32 +08:00
}
2024-06-05 20:25:26 +08:00
foreach (var circle in circles) {
circle.R = GetDistance(circle.Stroke.StylusPoints[0].ToPoint(),
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].ToPoint()) / 2;
2024-05-01 18:23:32 +08:00
circle.Centroid = new Point(
2024-06-05 20:25:26 +08:00
(circle.Stroke.StylusPoints[0].X +
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].X) / 2,
(circle.Stroke.StylusPoints[0].Y +
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].Y) / 2
2024-05-01 18:23:32 +08:00
);
2024-06-05 20:25:26 +08:00
}
;
if (lastTempManiputlaionMatrix == null) {
lastTempManiputlaionMatrix = m;
lastTempStrokeCollection = inkCanvas.Strokes;
}
2024-06-05 20:25:26 +08:00
else {
lastTempManiputlaionMatrix?.Append(m);
}
2024-05-01 18:23:32 +08:00
}
}
}
}
}