230 lines
7.3 KiB
C#
230 lines
7.3 KiB
C#
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
|
|
namespace XP.Camera.Calibration.Controls;
|
|
|
|
/// <summary>
|
|
/// 图像画布控件 - 提供图像显示、缩放、平移功能
|
|
/// </summary>
|
|
public partial class ImageCanvasControl : UserControl
|
|
{
|
|
private Point mouseDownPoint = new Point();
|
|
|
|
#region Dependency Properties
|
|
|
|
public static readonly DependencyProperty ZoomScaleProperty =
|
|
DependencyProperty.Register("ZoomScale", typeof(double), typeof(ImageCanvasControl), new PropertyMetadata(1.0));
|
|
|
|
public static readonly DependencyProperty ZoomCenterProperty =
|
|
DependencyProperty.Register("ZoomCenter", typeof(Point), typeof(ImageCanvasControl), new PropertyMetadata(new Point()));
|
|
|
|
public static readonly DependencyProperty PanningOffsetXProperty =
|
|
DependencyProperty.Register("PanningOffsetX", typeof(double), typeof(ImageCanvasControl), new PropertyMetadata(0.0));
|
|
|
|
public static readonly DependencyProperty PanningOffsetYProperty =
|
|
DependencyProperty.Register("PanningOffsetY", typeof(double), typeof(ImageCanvasControl), new PropertyMetadata(0.0));
|
|
|
|
public static readonly DependencyProperty ReferenceImageProperty =
|
|
DependencyProperty.Register("ReferenceImage", typeof(BitmapSource), typeof(ImageCanvasControl),
|
|
new UIPropertyMetadata(null, ReferenceImageChanged));
|
|
|
|
public static readonly DependencyProperty ImageScaleFactorProperty =
|
|
DependencyProperty.Register("ImageScaleFactor", typeof(double), typeof(ImageCanvasControl), new PropertyMetadata(1.0));
|
|
|
|
public static readonly DependencyProperty MaxImageWidthProperty =
|
|
DependencyProperty.Register("MaxImageWidth", typeof(int), typeof(ImageCanvasControl), new PropertyMetadata(0));
|
|
|
|
public static readonly DependencyProperty MaxImageHeightProperty =
|
|
DependencyProperty.Register("MaxImageHeight", typeof(int), typeof(ImageCanvasControl), new PropertyMetadata(0));
|
|
|
|
public static readonly DependencyProperty EnablePanningProperty =
|
|
DependencyProperty.Register("EnablePanning", typeof(bool), typeof(ImageCanvasControl), new PropertyMetadata(true));
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public double ZoomScale
|
|
{
|
|
get => (double)GetValue(ZoomScaleProperty);
|
|
set => SetValue(ZoomScaleProperty, value);
|
|
}
|
|
|
|
public Point ZoomCenter
|
|
{
|
|
get => (Point)GetValue(ZoomCenterProperty);
|
|
set => SetValue(ZoomCenterProperty, value);
|
|
}
|
|
|
|
public double PanningOffsetX
|
|
{
|
|
get => (double)GetValue(PanningOffsetXProperty);
|
|
set => SetValue(PanningOffsetXProperty, value);
|
|
}
|
|
|
|
public double PanningOffsetY
|
|
{
|
|
get => (double)GetValue(PanningOffsetYProperty);
|
|
set => SetValue(PanningOffsetYProperty, value);
|
|
}
|
|
|
|
public BitmapSource? ReferenceImage
|
|
{
|
|
get => (BitmapSource?)GetValue(ReferenceImageProperty);
|
|
set => SetValue(ReferenceImageProperty, value);
|
|
}
|
|
|
|
public double ImageScaleFactor
|
|
{
|
|
get => (double)GetValue(ImageScaleFactorProperty);
|
|
set => SetValue(ImageScaleFactorProperty, value);
|
|
}
|
|
|
|
public int MaxImageWidth
|
|
{
|
|
get => (int)GetValue(MaxImageWidthProperty);
|
|
set => SetValue(MaxImageWidthProperty, value);
|
|
}
|
|
|
|
public int MaxImageHeight
|
|
{
|
|
get => (int)GetValue(MaxImageHeightProperty);
|
|
set => SetValue(MaxImageHeightProperty, value);
|
|
}
|
|
|
|
public bool EnablePanning
|
|
{
|
|
get => (bool)GetValue(EnablePanningProperty);
|
|
set => SetValue(EnablePanningProperty, value);
|
|
}
|
|
|
|
private Canvas roiCanvas = new Canvas();
|
|
public Canvas RoiCanvas
|
|
{
|
|
get => roiCanvas;
|
|
set => roiCanvas = value;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
public event EventHandler<MouseButtonEventArgs>? CanvasRightMouseUp;
|
|
public event EventHandler<MouseButtonEventArgs>? CanvasRightMouseDown;
|
|
public event EventHandler<MouseButtonEventArgs>? CanvasLeftMouseDown;
|
|
public event EventHandler<MouseEventArgs>? CanvasMouseMove;
|
|
public event EventHandler<MouseWheelEventArgs>? CanvasMouseWheel;
|
|
|
|
#endregion
|
|
|
|
public ImageCanvasControl()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
#region Private Methods
|
|
|
|
private static void ReferenceImageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
(d as ImageCanvasControl)?.OnReferenceImageChanged(e.NewValue as BitmapSource);
|
|
}
|
|
|
|
private void OnReferenceImageChanged(BitmapSource? bitmapSource)
|
|
{
|
|
if (bitmapSource != null)
|
|
{
|
|
ImageBrush brush = new ImageBrush { ImageSource = bitmapSource, Stretch = Stretch.Uniform };
|
|
RoiCanvas.Background = brush;
|
|
RoiCanvas.Height = bitmapSource.Height;
|
|
RoiCanvas.Width = bitmapSource.Width;
|
|
}
|
|
else
|
|
{
|
|
RoiCanvas.Height = MaxImageHeight > 0 ? MaxImageHeight : 600;
|
|
RoiCanvas.Width = MaxImageWidth > 0 ? MaxImageWidth : 800;
|
|
RoiCanvas.Background = Brushes.LightGray;
|
|
}
|
|
}
|
|
|
|
private double CalculateScaleFactor()
|
|
{
|
|
if (ActualWidth <= 0) return 1;
|
|
double scaleFactor = Math.Max(RoiCanvas.Width / ActualWidth, RoiCanvas.Height / ActualHeight);
|
|
if (scaleFactor < 0)
|
|
scaleFactor = Math.Min(RoiCanvas.Width / ActualWidth, RoiCanvas.Height / ActualHeight);
|
|
return scaleFactor;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Event Handlers
|
|
|
|
private void Canvas_MouseEnter(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.LeftButton == MouseButtonState.Pressed)
|
|
mouseDownPoint = e.GetPosition(RoiCanvas);
|
|
}
|
|
|
|
private void Canvas_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
CanvasMouseMove?.Invoke(sender, e);
|
|
if (EnablePanning && e.LeftButton == MouseButtonState.Pressed)
|
|
{
|
|
Point mousePoint = e.GetPosition(RoiCanvas);
|
|
double mouseMoveLength = Point.Subtract(mousePoint, mouseDownPoint).Length;
|
|
if (mouseMoveLength > (10 * CalculateScaleFactor()) / ZoomScale)
|
|
{
|
|
PanningOffsetX += mousePoint.X - mouseDownPoint.X;
|
|
PanningOffsetY += mousePoint.Y - mouseDownPoint.Y;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { }
|
|
|
|
private void Canvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
|
|
{
|
|
CanvasRightMouseUp?.Invoke(sender, e);
|
|
}
|
|
|
|
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
mouseDownPoint = e.GetPosition(RoiCanvas);
|
|
CanvasLeftMouseDown?.Invoke(sender, e);
|
|
if (EnablePanning && e.ClickCount == 2)
|
|
{
|
|
ResetView();
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
CanvasRightMouseDown?.Invoke(sender, e);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void Adorner_MouseWheel(object sender, MouseWheelEventArgs e)
|
|
{
|
|
CanvasMouseWheel?.Invoke(sender, e);
|
|
}
|
|
|
|
private void ContentPresenter_SizeChanged(object sender, SizeChangedEventArgs e)
|
|
{
|
|
ImageScaleFactor = CalculateScaleFactor();
|
|
}
|
|
|
|
private void ResetView()
|
|
{
|
|
ZoomScale = 1.0;
|
|
PanningOffsetX = 0.0;
|
|
PanningOffsetY = 0.0;
|
|
ZoomCenter = new Point(0, 0);
|
|
}
|
|
|
|
#endregion
|
|
}
|