mirror of
https://gitee.com/wang-yin1/wpf-visual-process-framework
synced 2026-03-02 15:50:51 +08:00
259 lines
9.5 KiB
C#
259 lines
9.5 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Data;
|
||
using System.Windows.Documents;
|
||
using System.Windows.Input;
|
||
using System.Windows.Media;
|
||
using System.Windows.Media.Imaging;
|
||
using System.Windows.Navigation;
|
||
using System.Windows.Shapes;
|
||
|
||
namespace VisionFrame.Base.Controls
|
||
{
|
||
/// <summary>
|
||
/// 选框事件数据实体
|
||
/// </summary>
|
||
public class RectEventArgs : RoutedEventArgs
|
||
{
|
||
public Rect SelectRect { get; }
|
||
public double X { get; }
|
||
public double Y { get; }
|
||
public double Zoom { get; }
|
||
public RectEventArgs(RoutedEvent routedEvent, object source, Rect selectRect, double x, double y, double zoom)
|
||
: base(routedEvent, source)
|
||
{
|
||
SelectRect = selectRect;
|
||
X = x;
|
||
Y = y;
|
||
Zoom = zoom;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// CameraBox.xaml 的交互逻辑
|
||
/// </summary>
|
||
public partial class CameraBox : UserControl
|
||
{
|
||
/// <summary>
|
||
/// 图像源
|
||
/// </summary>
|
||
public System.Windows.Media.ImageSource ImageSource
|
||
{
|
||
get { return (System.Windows.Media.ImageSource)GetValue(ImageSourceProperty); }
|
||
set { SetValue(ImageSourceProperty, value); }
|
||
}
|
||
|
||
public static readonly DependencyProperty ImageSourceProperty =
|
||
DependencyProperty.Register("ImageSource", typeof(System.Windows.Media.ImageSource), typeof(CameraBox), new PropertyMetadata(callback));
|
||
|
||
private static void callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||
{
|
||
if (d is CameraBox box)
|
||
{
|
||
var source = e.NewValue as System.Windows.Media.ImageSource;
|
||
if (source != null)
|
||
{
|
||
box.image.Source = source;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 鼠标是否框选图像
|
||
/// </summary>
|
||
public bool IsMouseSelect
|
||
{
|
||
get { return (bool)GetValue(IsMouseSelectProperty); }
|
||
set { SetValue(IsMouseSelectProperty, value); }
|
||
}
|
||
|
||
public static readonly DependencyProperty IsMouseSelectProperty =
|
||
DependencyProperty.Register("IsMouseSelect", typeof(bool), typeof(CameraBox), new PropertyMetadata(false));
|
||
|
||
//定义路由事件
|
||
public static readonly RoutedEvent RectChangedEvent
|
||
= EventManager.RegisterRoutedEvent("RectChanged",
|
||
RoutingStrategy.Bubble,
|
||
typeof(RoutedEventHandler),
|
||
typeof(CameraBox));
|
||
|
||
/// <summary>
|
||
/// 选框更改事件
|
||
/// </summary>
|
||
public event RoutedEventHandler RectChanged
|
||
{
|
||
add { AddHandler(RectChangedEvent, value); }
|
||
remove { RemoveHandler(RectChangedEvent, value); }
|
||
}
|
||
|
||
protected virtual void OnRectChangedEvent(RectEventArgs e)
|
||
{
|
||
RaiseEvent(e);
|
||
}
|
||
|
||
//public void ClearSelectRect()
|
||
//{
|
||
// rect.Width = 0;
|
||
// rect.Height = 0;
|
||
// Canvas.SetLeft(rect, StartPoint.X);
|
||
// Canvas.SetTop(rect, StartPoint.Y);
|
||
//}
|
||
|
||
public TransformGroup TransformGroup { get; private set; } = new TransformGroup();
|
||
private ScaleTransform scaleTransform = new ScaleTransform();//缩放
|
||
private TranslateTransform translateTransform = new TranslateTransform();//平移
|
||
private Point MousePoint = new Point(-1, -1);
|
||
private Point StartPoint = new Point(0, 0);
|
||
private Point MouseDownPoint = new Point(0, 0);//鼠标按下位置
|
||
private double scale = 1;//默认放大倍数
|
||
private int viewportWidth = 0;
|
||
private int viewportHeight = 0;
|
||
private int imageBoxWidth = 0;
|
||
private int imageBoxHeight = 0;
|
||
private bool mousePressed = false;
|
||
public double Scale { get; set; } = 1;
|
||
/// <summary>
|
||
/// 鼠标框选区域
|
||
/// </summary>
|
||
public Rect SelectRect { get; private set; }
|
||
public CameraBox()
|
||
{
|
||
InitializeComponent();
|
||
Loaded += CameraBox_Loaded;
|
||
}
|
||
private void CameraBox_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
SetTransform();
|
||
Loaded -= CameraBox_Loaded;//只加载一次SetTransform()
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据viewport尺寸,设置图像的缩放和平移
|
||
/// </summary>
|
||
private void SetTransform()
|
||
{
|
||
TransformGroup.Children.Add(scaleTransform);
|
||
TransformGroup.Children.Add(translateTransform);
|
||
imagebox.RenderTransform = TransformGroup;
|
||
viewportWidth = (int)viewport.ActualWidth;
|
||
viewportHeight = (int)viewport.ActualHeight;
|
||
imageBoxWidth = (int)imagebox.ActualWidth;
|
||
imageBoxHeight = (int)imagebox.ActualHeight;
|
||
|
||
scale = Math.Min(1.0 * viewportWidth / imageBoxWidth, 1.0 * viewportHeight / imageBoxHeight);//最初放大比
|
||
scaleTransform.ScaleX = scale;
|
||
scaleTransform.ScaleY = scale;
|
||
|
||
var translateX = (viewportWidth - imageBoxWidth * scale) / 2;
|
||
var translateY = (viewportHeight - imageBoxHeight * scale) / 2;
|
||
translateTransform.X = translateX;
|
||
translateTransform.Y = translateY;
|
||
textblock.Text = $"({Math.Round(translateX)},{Math.Round(translateY)}) Zoom:{scale}";
|
||
}
|
||
|
||
//鼠标右键弹起:还原图像
|
||
private void viewport_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
|
||
{
|
||
scaleTransform.ScaleX = scale;//还原最初放大比
|
||
scaleTransform.ScaleY = scale;
|
||
var translateX = (viewportWidth - imageBoxWidth * scale) / 2;
|
||
var translateY = (viewportHeight - imageBoxHeight * scale) / 2;
|
||
translateTransform.X = translateX;
|
||
translateTransform.Y = translateY;
|
||
}
|
||
|
||
//鼠标左键按下
|
||
private void viewport_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||
{
|
||
mousePressed = true;
|
||
MouseDownPoint = e.GetPosition(viewport);
|
||
|
||
////选框初始位置
|
||
//StartPoint = e.GetPosition(viewport);
|
||
//rect.Width = 0;
|
||
//rect.Height = 0;
|
||
//Canvas.SetLeft(rect, StartPoint.X);
|
||
//Canvas.SetTop(rect, StartPoint.Y);
|
||
|
||
////选框坐标显示
|
||
//rectLabel.Text = string.Empty;
|
||
//Canvas.SetLeft(rectLabel, StartPoint.X);
|
||
//Canvas.SetTop(rectLabel, StartPoint.Y);
|
||
//viewport.CaptureMouse();
|
||
|
||
}
|
||
|
||
|
||
//鼠标移动
|
||
private void viewport_MouseMove(object sender, MouseEventArgs e)
|
||
{
|
||
Point point = e.GetPosition(viewport);
|
||
MousePoint = point;//更新鼠标位置
|
||
if (!mousePressed)
|
||
return;
|
||
if (IsMouseSelect)
|
||
{
|
||
////表示框选图像
|
||
//rect.Width = point.X - StartPoint.X < 0 ? 0 : point.X - StartPoint.X;
|
||
//rect.Height = point.Y - StartPoint.Y < 0 ? 0 : point.Y - StartPoint.Y;
|
||
//SelectRect = new Rect(StartPoint.X, StartPoint.Y, rect.Width, rect.Height);
|
||
//rectLabel.Text = $"{SelectRect}";
|
||
//Canvas.SetLeft(rectLabel, SelectRect.X + SelectRect.Width);
|
||
//Canvas.SetTop(rectLabel, StartPoint.Y);
|
||
//if (SelectRect.Width + SelectRect.Height == 0)
|
||
//{
|
||
// rectLabel.Text = string.Empty;
|
||
//}
|
||
}
|
||
else
|
||
{
|
||
//表示移动图像
|
||
translateTransform.X += point.X - MouseDownPoint.X;
|
||
translateTransform.Y += point.Y - MouseDownPoint.Y;
|
||
MouseDownPoint = point;
|
||
textblock.Text = $"({Math.Round(translateTransform.X)},{Math.Round(translateTransform.Y)}) Zoom:{scale}";
|
||
}
|
||
}
|
||
|
||
//鼠标左键弹起
|
||
private void viewport_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||
{
|
||
mousePressed = false;
|
||
MouseDownPoint = e.GetPosition(viewport);
|
||
viewport.ReleaseMouseCapture();
|
||
|
||
if (IsMouseSelect)
|
||
{
|
||
OnRectChangedEvent(new RectEventArgs(RectChangedEvent, this, SelectRect, translateTransform.X, translateTransform.Y, scaleTransform.ScaleX));
|
||
}
|
||
}
|
||
|
||
private void viewport_MouseLeave(object sender, MouseEventArgs e)
|
||
{
|
||
MousePoint = new Point(-1, -1);
|
||
}
|
||
|
||
//放大缩小图像
|
||
private void viewport_MouseWheel(object sender, MouseWheelEventArgs e)
|
||
{
|
||
double scale = e.Delta * 0.0005;
|
||
Point point = e.GetPosition(viewport);
|
||
Point inverse = TransformGroup.Inverse.Transform(point);
|
||
if ((scaleTransform.ScaleX + scale < 0.1) || (scaleTransform.ScaleX + scale > 2))
|
||
{
|
||
return;
|
||
}
|
||
scaleTransform.ScaleX += scale;
|
||
scaleTransform.ScaleY += scale;
|
||
translateTransform.X = -1 * (inverse.X * scaleTransform.ScaleX - point.X);
|
||
translateTransform.Y = -1 * (inverse.Y * scaleTransform.ScaleY - point.Y);
|
||
textblock.Text = $"({Math.Round(translateTransform.X)},{Math.Round(translateTransform.Y)}) Zoom:{scale}";
|
||
}
|
||
}
|
||
}
|