mirror of
https://gitee.com/wang-yin1/wpf-visual-process-framework
synced 2026-03-03 00:00:56 +08:00
2025-07-16 12:19
This commit is contained in:
25
VisionFrame.Base/Controls/CameraBox.xaml
Normal file
25
VisionFrame.Base/Controls/CameraBox.xaml
Normal file
@@ -0,0 +1,25 @@
|
||||
<UserControl x:Class="VisionFrame.Base.Controls.CameraBox"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:VisionFrame.Base.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid x:Name="viewport" Background="Transparent"
|
||||
MouseLeftButtonDown="viewport_MouseLeftButtonDown"
|
||||
MouseLeftButtonUp="viewport_MouseLeftButtonUp"
|
||||
MouseRightButtonUp="viewport_MouseRightButtonUp"
|
||||
MouseMove="viewport_MouseMove"
|
||||
MouseLeave="viewport_MouseLeave"
|
||||
MouseWheel="viewport_MouseWheel">
|
||||
<Canvas ClipToBounds="True">
|
||||
<Grid x:Name="imagebox">
|
||||
<Image x:Name="image"/>
|
||||
</Grid>
|
||||
<!--<Rectangle x:Name="rect" Stroke="Red" StrokeThickness="1" Fill="Transparent"/>-->
|
||||
<TextBlock x:Name="rectLabel" Foreground="Green" FontSize="12"/>
|
||||
</Canvas>
|
||||
<TextBlock x:Name="textblock" Foreground="Green" Text="0" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="15"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
258
VisionFrame.Base/Controls/CameraBox.xaml.cs
Normal file
258
VisionFrame.Base/Controls/CameraBox.xaml.cs
Normal file
@@ -0,0 +1,258 @@
|
||||
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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user