Files
community/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs
T

558 lines
22 KiB
C#
Raw Normal View History

2025-08-03 16:46:33 +08:00
using iNKORE.UI.WPF.Modern.Controls;
2025-05-25 09:29:48 +08:00
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
2025-07-28 11:15:35 +08:00
using System.Windows.Shapes;
2025-07-30 14:18:45 +08:00
using System.Windows.Threading;
2025-05-25 09:29:48 +08:00
using Point = System.Windows.Point;
2025-08-03 16:46:33 +08:00
namespace Ink_Canvas
{
public partial class MainWindow : Window
{
2025-05-25 09:29:48 +08:00
#region Floating Control
private object lastBorderMouseDownObject;
2025-08-03 16:46:33 +08:00
private void Border_MouseDown(object sender, MouseButtonEventArgs e)
{
// 如果发送者是 RandomDrawPanel 或 SingleDrawPanel,且它们被隐藏,则不处理事件
2025-08-03 16:46:33 +08:00
if (sender is SimpleStackPanel panel)
{
if ((panel == RandomDrawPanel || panel == SingleDrawPanel) &&
panel.Visibility != Visibility.Visible)
{
return;
}
}
2025-08-30 21:18:34 +08:00
2025-05-25 09:29:48 +08:00
lastBorderMouseDownObject = sender;
}
2025-07-28 14:40:44 +08:00
private bool isStrokeSelectionCloneOn;
2025-05-25 09:29:48 +08:00
2025-08-03 16:46:33 +08:00
private void BorderStrokeSelectionClone_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
2025-08-03 16:46:33 +08:00
if (isStrokeSelectionCloneOn)
{
2025-05-25 09:29:48 +08:00
BorderStrokeSelectionClone.Background = Brushes.Transparent;
isStrokeSelectionCloneOn = false;
}
2025-08-03 16:46:33 +08:00
else
{
2025-05-25 09:29:48 +08:00
BorderStrokeSelectionClone.Background = new SolidColorBrush(StringToColor("#FF1ED760"));
isStrokeSelectionCloneOn = true;
}
}
2025-08-03 16:46:33 +08:00
private void BorderStrokeSelectionCloneToNewBoard_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
var strokes = inkCanvas.GetSelectedStrokes();
inkCanvas.Select(new StrokeCollection());
strokes = strokes.Clone();
BtnWhiteBoardAdd_Click(null, null);
inkCanvas.Strokes.Add(strokes);
}
2025-08-03 16:46:33 +08:00
private void BorderStrokeSelectionDelete_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
SymbolIconDelete_MouseUp(sender, e);
}
2025-08-03 16:46:33 +08:00
private void GridPenWidthDecrease_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
ChangeStrokeThickness(0.8);
}
2025-08-03 16:46:33 +08:00
private void GridPenWidthIncrease_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
ChangeStrokeThickness(1.25);
}
2025-08-03 16:46:33 +08:00
private void ChangeStrokeThickness(double multipler)
{
foreach (var stroke in inkCanvas.GetSelectedStrokes())
{
2025-05-25 09:29:48 +08:00
var newWidth = stroke.DrawingAttributes.Width * multipler;
var newHeight = stroke.DrawingAttributes.Height * multipler;
if (!(newWidth >= DrawingAttributes.MinWidth) || !(newWidth <= DrawingAttributes.MaxWidth)
|| !(newHeight >= DrawingAttributes.MinHeight) ||
!(newHeight <= DrawingAttributes.MaxHeight)) continue;
stroke.DrawingAttributes.Width = newWidth;
stroke.DrawingAttributes.Height = newHeight;
}
2025-08-30 21:18:34 +08:00
2025-05-25 09:29:48 +08:00
if (DrawingAttributesHistory.Count > 0)
{
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
2025-08-03 16:46:33 +08:00
private void GridPenWidthRestore_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
2025-08-03 16:46:33 +08:00
foreach (var stroke in inkCanvas.GetSelectedStrokes())
{
2025-05-25 09:29:48 +08:00
stroke.DrawingAttributes.Width = inkCanvas.DefaultDrawingAttributes.Width;
stroke.DrawingAttributes.Height = inkCanvas.DefaultDrawingAttributes.Height;
}
}
2025-08-03 16:46:33 +08:00
private void ImageFlipHorizontal_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.ScaleAt(-1, 1, center.X, center.Y); // 缩放
var targetStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in targetStrokes) stroke.Transform(m, false);
if (DrawingAttributesHistory.Count > 0)
{
//var collecion = new StrokeCollection();
//foreach (var item in DrawingAttributesHistory)
//{
// collecion.Add(item.Key);
//}
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
//updateBorderStrokeSelectionControlLocation();
}
2025-08-03 16:46:33 +08:00
private void ImageFlipVertical_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.ScaleAt(1, -1, center.X, center.Y); // 缩放
var targetStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in targetStrokes) stroke.Transform(m, false);
if (DrawingAttributesHistory.Count > 0)
{
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
2025-08-03 16:46:33 +08:00
// ... existing code ...
private void ImageRotate45_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
2025-07-31 13:23:33 +08:00
m.RotateAt(45, center.X, center.Y); // 顺时针旋转45度
2025-05-25 09:29:48 +08:00
var targetStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in targetStrokes) stroke.Transform(m, false);
if (DrawingAttributesHistory.Count > 0)
{
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
2025-08-03 16:46:33 +08:00
private void ImageRotate90_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (lastBorderMouseDownObject != sender) return;
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.RotateAt(90, center.X, center.Y); // 旋转
var targetStrokes = inkCanvas.GetSelectedStrokes();
foreach (var stroke in targetStrokes) stroke.Transform(m, false);
if (DrawingAttributesHistory.Count > 0)
{
var collecion = new StrokeCollection();
foreach (var item in DrawingAttributesHistory)
{
collecion.Add(item.Key);
}
2025-08-30 21:18:34 +08:00
2025-05-25 09:29:48 +08:00
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
#endregion
2025-07-28 14:40:44 +08:00
private bool isGridInkCanvasSelectionCoverMouseDown;
2025-05-25 09:29:48 +08:00
private StrokeCollection StrokesSelectionClone = new StrokeCollection();
2025-08-03 16:46:33 +08:00
private void GridInkCanvasSelectionCover_MouseDown(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
isGridInkCanvasSelectionCoverMouseDown = true;
}
2025-08-03 16:46:33 +08:00
private void GridInkCanvasSelectionCover_MouseUp(object sender, MouseButtonEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (!isGridInkCanvasSelectionCoverMouseDown) return;
isGridInkCanvasSelectionCoverMouseDown = false;
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
}
2025-08-03 16:46:33 +08:00
private void BtnSelect_Click(object sender, RoutedEventArgs e)
{
2025-07-18 17:59:17 +08:00
ExitMultiTouchModeIfNeeded();
2025-05-25 09:29:48 +08:00
forceEraser = true;
drawingShapeMode = 0;
inkCanvas.IsManipulationEnabled = false;
2025-08-03 16:46:33 +08:00
if (inkCanvas.EditingMode == InkCanvasEditingMode.Select)
{
if (inkCanvas.GetSelectedStrokes().Count == inkCanvas.Strokes.Count)
{
2025-08-30 11:20:53 +08:00
// 使用集中化的工具模式切换方法
2025-08-30 21:18:34 +08:00
SetCurrentToolMode(InkCanvasEditingMode.Ink,
() => { SetCurrentToolMode(InkCanvasEditingMode.Select); });
2025-05-25 09:29:48 +08:00
}
2025-08-03 16:46:33 +08:00
else
{
2025-05-25 09:29:48 +08:00
var selectedStrokes = new StrokeCollection();
foreach (var stroke in inkCanvas.Strokes)
if (stroke.GetBounds().Width > 0 && stroke.GetBounds().Height > 0)
selectedStrokes.Add(stroke);
inkCanvas.Select(selectedStrokes);
}
}
2025-08-03 16:46:33 +08:00
else
{
2025-08-30 11:20:53 +08:00
// 使用集中化的工具模式切换方法
SetCurrentToolMode(InkCanvasEditingMode.Select);
2025-05-25 09:29:48 +08:00
}
}
private double BorderStrokeSelectionControlWidth = 490.0;
private double BorderStrokeSelectionControlHeight = 80.0;
2025-07-28 14:40:44 +08:00
private bool isProgramChangeStrokeSelection;
2025-05-25 09:29:48 +08:00
2025-08-03 16:46:33 +08:00
private void inkCanvas_SelectionChanged(object sender, EventArgs e)
{
2025-05-25 09:29:48 +08:00
if (isProgramChangeStrokeSelection) return;
2025-08-03 16:46:33 +08:00
if (inkCanvas.GetSelectedStrokes().Count == 0)
{
2025-05-25 09:29:48 +08:00
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
2025-08-30 21:18:34 +08:00
2025-05-25 09:29:48 +08:00
}
2025-08-03 16:46:33 +08:00
else
{
2025-05-25 09:29:48 +08:00
GridInkCanvasSelectionCover.Visibility = Visibility.Visible;
BorderStrokeSelectionClone.Background = Brushes.Transparent;
isStrokeSelectionCloneOn = false;
updateBorderStrokeSelectionControlLocation();
2025-07-28 11:15:35 +08:00
2025-05-25 09:29:48 +08:00
}
}
2025-08-30 21:18:34 +08:00
2025-08-03 16:46:33 +08:00
private void updateBorderStrokeSelectionControlLocation()
{
2025-05-25 09:29:48 +08:00
var borderLeft = (inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Right -
BorderStrokeSelectionControlWidth) / 2;
var borderTop = inkCanvas.GetSelectionBounds().Bottom + 1;
if (borderLeft < 0) borderLeft = 0;
if (borderTop < 0) borderTop = 0;
if (Width - borderLeft < BorderStrokeSelectionControlWidth || double.IsNaN(borderLeft))
borderLeft = Width - BorderStrokeSelectionControlWidth;
if (Height - borderTop < BorderStrokeSelectionControlHeight || double.IsNaN(borderTop))
borderTop = Height - BorderStrokeSelectionControlHeight;
if (borderTop > 60) borderTop -= 60;
BorderStrokeSelectionControl.Margin = new Thickness(borderLeft, borderTop, 0, 0);
}
2025-08-03 16:46:33 +08:00
private void GridInkCanvasSelectionCover_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
2025-05-25 09:29:48 +08:00
e.Mode = ManipulationModes.All;
}
2025-08-03 16:46:33 +08:00
private void GridInkCanvasSelectionCover_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
2025-05-25 09:29:48 +08:00
if (StrokeManipulationHistory?.Count > 0)
{
timeMachine.CommitStrokeManipulationHistory(StrokeManipulationHistory);
foreach (var item in StrokeManipulationHistory)
{
StrokeInitialHistory[item.Key] = item.Value.Item2;
}
2025-08-30 21:18:34 +08:00
2025-05-25 09:29:48 +08:00
StrokeManipulationHistory = null;
}
2025-08-30 21:18:34 +08:00
2025-05-25 09:29:48 +08:00
if (DrawingAttributesHistory.Count > 0)
{
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
foreach (var item in DrawingAttributesHistoryFlag)
{
item.Value.Clear();
}
}
}
2025-08-03 16:46:33 +08:00
private void GridInkCanvasSelectionCover_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
try
{
if (dec.Count >= 1)
{
2025-07-23 22:57:16 +08:00
bool disableScale = dec.Count >= 3;
2025-05-25 09:29:48 +08:00
var md = e.DeltaManipulation;
var trans = md.Translation; // 获得位移矢量
var rotate = md.Rotation; // 获得旋转角度
var scale = md.Scale; // 获得缩放倍数
var m = new Matrix();
// Find center of element and then transform to get current location of center
var fe = e.Source as FrameworkElement;
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.Translate(trans.X, trans.Y); // 移动
2025-06-19 22:49:11 +08:00
if (!disableScale)
m.ScaleAt(scale.X, scale.Y, center.X, center.Y); // 缩放
2025-05-25 09:29:48 +08:00
var strokes = inkCanvas.GetSelectedStrokes();
if (StrokesSelectionClone.Count != 0)
strokes = StrokesSelectionClone;
else if (Settings.Gesture.IsEnableTwoFingerRotationOnSelection)
m.RotateAt(rotate, center.X, center.Y); // 旋转
2025-08-03 16:46:33 +08:00
foreach (var stroke in strokes)
{
2025-05-25 09:29:48 +08:00
stroke.Transform(m, false);
2025-08-03 16:46:33 +08:00
try
{
2025-05-25 09:29:48 +08:00
stroke.DrawingAttributes.Width *= md.Scale.X;
stroke.DrawingAttributes.Height *= md.Scale.Y;
}
2025-08-30 21:18:34 +08:00
catch
{
}
2025-05-25 09:29:48 +08:00
}
updateBorderStrokeSelectionControlLocation();
}
}
2025-08-30 21:18:34 +08:00
catch
{
}
2025-05-25 09:29:48 +08:00
}
2025-08-30 21:18:34 +08:00
private void GridInkCanvasSelectionCover_TouchDown(object sender, TouchEventArgs e)
{
}
2025-05-25 09:29:48 +08:00
2025-08-30 21:18:34 +08:00
private void GridInkCanvasSelectionCover_TouchUp(object sender, TouchEventArgs e)
{
}
2025-05-25 09:29:48 +08:00
private Point lastTouchPointOnGridInkCanvasCover = new Point(0, 0);
2025-08-03 16:46:33 +08:00
private void GridInkCanvasSelectionCover_PreviewTouchDown(object sender, TouchEventArgs e)
{
2025-05-25 09:29:48 +08:00
dec.Add(e.TouchDevice.Id);
//设备1个的时候,记录中心点
2025-08-03 16:46:33 +08:00
if (dec.Count == 1)
{
2025-05-25 09:29:48 +08:00
var touchPoint = e.GetTouchPoint(null);
centerPoint = touchPoint.Position;
lastTouchPointOnGridInkCanvasCover = touchPoint.Position;
2025-08-03 16:46:33 +08:00
if (isStrokeSelectionCloneOn)
{
2025-05-25 09:29:48 +08:00
var strokes = inkCanvas.GetSelectedStrokes();
isProgramChangeStrokeSelection = true;
inkCanvas.Select(new StrokeCollection());
StrokesSelectionClone = strokes.Clone();
inkCanvas.Select(strokes);
isProgramChangeStrokeSelection = false;
inkCanvas.Strokes.Add(StrokesSelectionClone);
}
2025-08-03 16:46:33 +08:00
else
{
2025-06-17 13:20:06 +08:00
// 新增:启动套索选择模式
2025-08-30 11:20:53 +08:00
// 使用集中化的工具模式切换方法
SetCurrentToolMode(InkCanvasEditingMode.Select);
2025-06-17 13:20:06 +08:00
inkCanvas.Select(new StrokeCollection());
}
2025-05-25 09:29:48 +08:00
}
}
2025-08-03 16:46:33 +08:00
private void GridInkCanvasSelectionCover_PreviewTouchUp(object sender, TouchEventArgs e)
{
2025-05-25 09:29:48 +08:00
dec.Remove(e.TouchDevice.Id);
if (dec.Count >= 1) return;
isProgramChangeStrokeSelection = false;
2025-08-03 16:46:33 +08:00
if (lastTouchPointOnGridInkCanvasCover == e.GetTouchPoint(null).Position)
{
2025-05-25 09:29:48 +08:00
if (!(lastTouchPointOnGridInkCanvasCover.X < inkCanvas.GetSelectionBounds().Left) &&
!(lastTouchPointOnGridInkCanvasCover.Y < inkCanvas.GetSelectionBounds().Top) &&
!(lastTouchPointOnGridInkCanvasCover.X > inkCanvas.GetSelectionBounds().Right) &&
!(lastTouchPointOnGridInkCanvasCover.Y > inkCanvas.GetSelectionBounds().Bottom)) return;
inkCanvas.Select(new StrokeCollection());
StrokesSelectionClone = new StrokeCollection();
}
2025-08-03 16:46:33 +08:00
else if (inkCanvas.GetSelectedStrokes().Count == 0)
{
2025-05-25 09:29:48 +08:00
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
StrokesSelectionClone = new StrokeCollection();
}
2025-08-03 16:46:33 +08:00
else
{
2025-05-25 09:29:48 +08:00
GridInkCanvasSelectionCover.Visibility = Visibility.Visible;
StrokesSelectionClone = new StrokeCollection();
}
}
2025-07-18 16:12:04 +08:00
2025-08-03 16:46:33 +08:00
private void LassoSelect_Click(object sender, RoutedEventArgs e)
{
2025-07-18 17:59:17 +08:00
ExitMultiTouchModeIfNeeded();
2025-07-18 16:12:04 +08:00
forceEraser = false;
forcePointEraser = false;
drawingShapeMode = 0;
2025-08-30 11:20:53 +08:00
// 使用集中化的工具模式切换方法
SetCurrentToolMode(InkCanvasEditingMode.Select);
2025-07-18 16:12:04 +08:00
SetCursorBasedOnEditingMode(inkCanvas);
}
2025-08-03 16:46:33 +08:00
private void BtnLassoSelect_Click(object sender, RoutedEventArgs e)
{
2025-07-18 17:59:17 +08:00
ExitMultiTouchModeIfNeeded();
2025-07-18 16:12:04 +08:00
forceEraser = false;
forcePointEraser = false;
drawingShapeMode = 0;
2025-08-30 11:20:53 +08:00
// 使用集中化的工具模式切换方法
SetCurrentToolMode(InkCanvasEditingMode.Select);
2025-07-18 16:12:04 +08:00
inkCanvas.IsManipulationEnabled = true;
SetCursorBasedOnEditingMode(inkCanvas);
}
2025-07-28 11:15:35 +08:00
#region UIElement Selection and Resize
2025-08-30 21:18:34 +08:00
2025-07-28 11:15:35 +08:00
private Rect GetUIElementBounds(UIElement element)
{
2025-07-30 14:18:45 +08:00
if (element is FrameworkElement fe)
{
var left = InkCanvas.GetLeft(element);
var top = InkCanvas.GetTop(element);
2025-07-28 11:15:35 +08:00
2025-07-30 14:18:45 +08:00
if (double.IsNaN(left)) left = 0;
if (double.IsNaN(top)) top = 0;
2025-07-28 11:15:35 +08:00
2025-07-30 14:18:45 +08:00
var width = fe.ActualWidth > 0 ? fe.ActualWidth : fe.Width;
var height = fe.ActualHeight > 0 ? fe.ActualHeight : fe.Height;
2025-07-28 11:15:35 +08:00
2025-07-30 14:18:45 +08:00
// 检查是否有RenderTransform
if (fe.RenderTransform != null && fe.RenderTransform != Transform.Identity)
{
try
{
// 如果有变换,使用变换后的边界
var transform = element.TransformToAncestor(inkCanvas);
var elementBounds = new Rect(0, 0, width, height);
var transformedBounds = transform.TransformBounds(elementBounds);
return transformedBounds;
}
catch
{
// 变换失败时回退到简单计算
return new Rect(left, top, width, height);
}
}
else
{
// 没有变换时直接使用位置和大小
return new Rect(left, top, width, height);
}
2025-07-28 11:15:35 +08:00
}
2025-07-30 14:18:45 +08:00
return new Rect(0, 0, 0, 0);
2025-07-28 11:15:35 +08:00
}
2025-05-25 09:29:48 +08:00
}
2025-08-30 21:18:34 +08:00
}
#endregion