2025-07-16 12:19

This commit is contained in:
wang-yin1
2025-07-16 12:20:02 +08:00
parent ca823a9294
commit 25d7fc3330
13 changed files with 801 additions and 305 deletions

View 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>

View 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}";
}
}
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0-windows</TargetFramework>