877 lines
31 KiB
C#
877 lines
31 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Data;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Animation;
|
|
using System.Windows.Media.Imaging;
|
|
using HandyControl.Data;
|
|
using HandyControl.Interactivity;
|
|
using HandyControl.Properties.Langs;
|
|
using HandyControl.Tools;
|
|
using Microsoft.Win32;
|
|
|
|
namespace HandyControl.Controls
|
|
{
|
|
[TemplatePart(Name = ElementPanelMain, Type = typeof(Panel))]
|
|
[TemplatePart(Name = ElementCanvasSmallImg, Type = typeof(Canvas))]
|
|
[TemplatePart(Name = ElementBorderMove, Type = typeof(Border))]
|
|
[TemplatePart(Name = ElementBorderBottom, Type = typeof(Border))]
|
|
[TemplatePart(Name = ElementImageMain, Type = typeof(Image))]
|
|
public class ImageViewer : Control
|
|
{
|
|
#region Constants
|
|
|
|
private const string ElementPanelMain = "PART_PanelMain";
|
|
|
|
private const string ElementCanvasSmallImg = "PART_CanvasSmallImg";
|
|
|
|
private const string ElementBorderMove = "PART_BorderMove";
|
|
|
|
private const string ElementBorderBottom = "PART_BorderBottom";
|
|
|
|
private const string ElementImageMain = "PART_ImageMain";
|
|
|
|
/// <summary>
|
|
/// 缩放比间隔
|
|
/// </summary>
|
|
private const double ScaleInternal = 0.2;
|
|
|
|
#endregion Constants
|
|
|
|
#region Data
|
|
|
|
/// <summary>
|
|
/// 图片保存对话框
|
|
/// </summary>
|
|
private static readonly SaveFileDialog SaveFileDialog = new SaveFileDialog
|
|
{
|
|
Filter = $"{Lang.PngImg}|*.png"
|
|
};
|
|
|
|
private Panel _panelMain;
|
|
|
|
private Canvas _canvasSmallImg;
|
|
|
|
private Border _borderMove;
|
|
|
|
private Border _borderBottom;
|
|
|
|
private Image _imageMain;
|
|
|
|
/// <summary>
|
|
/// 右下角小图片是否加载过
|
|
/// </summary>
|
|
private bool _borderSmallIsLoaded;
|
|
|
|
/// <summary>
|
|
/// 图片是否可以在x轴方向移动
|
|
/// </summary>
|
|
private bool _canMoveX;
|
|
|
|
/// <summary>
|
|
/// 图片是否可以在y轴方向移动
|
|
/// </summary>
|
|
private bool _canMoveY;
|
|
|
|
/// <summary>
|
|
/// 图片实际位置
|
|
/// </summary>
|
|
private Thickness _imgActualMargin;
|
|
|
|
/// <summary>
|
|
/// 图片实际旋转角度
|
|
/// </summary>
|
|
private double _imgActualRotate;
|
|
|
|
/// <summary>
|
|
/// 图片实际旋缩放比
|
|
/// </summary>
|
|
private double _imgActualScale = 1;
|
|
|
|
/// <summary>
|
|
/// 在图片上鼠标移动时的即时位置
|
|
/// </summary>
|
|
private Point _imgCurrentPoint;
|
|
|
|
/// <summary>
|
|
/// 鼠标是否在图片上按下左键
|
|
/// </summary>
|
|
private bool _imgIsMouseLeftButtonDown;
|
|
|
|
/// <summary>
|
|
/// 在图片上按下时图片的位置
|
|
/// </summary>
|
|
private Thickness _imgMouseDownMargin;
|
|
|
|
/// <summary>
|
|
/// 在图片上按下时鼠标的位置
|
|
/// </summary>
|
|
private Point _imgMouseDownPoint;
|
|
|
|
/// <summary>
|
|
/// 在小图片上鼠标移动时的即时位置
|
|
/// </summary>
|
|
private Point _imgSmallCurrentPoint;
|
|
|
|
/// <summary>
|
|
/// 鼠标是否在小图片上按下左键
|
|
/// </summary>
|
|
private bool _imgSmallIsMouseLeftButtonDown;
|
|
|
|
/// <summary>
|
|
/// 在小图片上按下时图片的位置
|
|
/// </summary>
|
|
private Thickness _imgSmallMouseDownMargin;
|
|
|
|
/// <summary>
|
|
/// 在小图片上按下时鼠标的位置
|
|
/// </summary>
|
|
private Point _imgSmallMouseDownPoint;
|
|
|
|
/// <summary>
|
|
/// 图片长宽比
|
|
/// </summary>
|
|
private double _imgWidHeiScale;
|
|
|
|
/// <summary>
|
|
/// 图片是否倾斜
|
|
/// </summary>
|
|
private bool _isOblique;
|
|
|
|
/// <summary>
|
|
/// 缩放高度间隔
|
|
/// </summary>
|
|
private double _scaleInternalHeight;
|
|
|
|
/// <summary>
|
|
/// 缩放宽度间隔
|
|
/// </summary>
|
|
private double _scaleInternalWidth;
|
|
|
|
/// <summary>
|
|
/// 底部BorderBottom(包含一些图片操作)是否显示中
|
|
/// </summary>
|
|
private bool _showBorderBottom;
|
|
|
|
#endregion Data
|
|
|
|
#region ctor
|
|
|
|
public ImageViewer()
|
|
{
|
|
CommandBindings.Add(new CommandBinding(ControlCommands.Save, ButtonSave_OnClick));
|
|
CommandBindings.Add(new CommandBinding(ControlCommands.Open, ButtonWindowsOpen_OnClick));
|
|
CommandBindings.Add(new CommandBinding(ControlCommands.Restore, ButtonActual_OnClick));
|
|
CommandBindings.Add(new CommandBinding(ControlCommands.Reduce, ButtonReduce_OnClick));
|
|
CommandBindings.Add(new CommandBinding(ControlCommands.Enlarge, ButtonEnlarge_OnClick));
|
|
CommandBindings.Add(new CommandBinding(ControlCommands.RotateLeft, ButtonRotateLeft_OnClick));
|
|
CommandBindings.Add(new CommandBinding(ControlCommands.RotateRight, ButtonRotateRight_OnClick));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 带一个图片Uri的构造函数
|
|
/// </summary>
|
|
/// <param name="uri"></param>
|
|
public ImageViewer(Uri uri) : this()
|
|
{
|
|
try
|
|
{
|
|
ImageSource = BitmapFrame.Create(uri);
|
|
ImgPath = uri.AbsolutePath;
|
|
if (File.Exists(ImgPath))
|
|
{
|
|
var info = new FileInfo(ImgPath);
|
|
ImgSize = info.Length;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show(Lang.ErrorImgPath);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 带一个图片路径的构造函数
|
|
/// </summary>
|
|
/// <param name="path"></param>
|
|
public ImageViewer(string path) : this(new Uri(path))
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public static readonly DependencyProperty ShowImgMapProperty = DependencyProperty.Register(
|
|
"ShowImgMap", typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
|
|
|
|
public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register(
|
|
"ImageSource", typeof(BitmapFrame), typeof(ImageViewer), new PropertyMetadata(default(BitmapFrame)));
|
|
|
|
public static readonly DependencyProperty IsFullScreenProperty = DependencyProperty.Register(
|
|
"IsFullScreen", typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
|
|
|
|
internal static readonly DependencyProperty ImgPathProperty = DependencyProperty.Register(
|
|
"ImgPath", typeof(string), typeof(ImageViewer), new PropertyMetadata(default(string)));
|
|
|
|
internal static readonly DependencyProperty ImgSizeProperty = DependencyProperty.Register(
|
|
"ImgSize", typeof(long), typeof(ImageViewer), new PropertyMetadata(-1L));
|
|
|
|
/// <summary>
|
|
/// 是否显示全屏按钮
|
|
/// </summary>
|
|
internal static readonly DependencyProperty ShowFullScreenButtonProperty = DependencyProperty.Register(
|
|
"ShowFullScreenButton", typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
|
|
|
|
/// <summary>
|
|
/// 关闭按钮是否显示中
|
|
/// </summary>
|
|
internal static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register(
|
|
"ShowCloseButton", typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
|
|
|
|
internal static readonly DependencyProperty ImageContentProperty = DependencyProperty.Register(
|
|
"ImageContent", typeof(object), typeof(ImageViewer), new PropertyMetadata(default(object)));
|
|
|
|
internal static readonly DependencyProperty ImageMarginProperty = DependencyProperty.Register(
|
|
"ImageMargin", typeof(Thickness), typeof(ImageViewer), new PropertyMetadata(default(Thickness)));
|
|
|
|
internal static readonly DependencyProperty ImageWidthProperty = DependencyProperty.Register(
|
|
"ImageWidth", typeof(double), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.Double0Box));
|
|
|
|
internal static readonly DependencyProperty ImageHeightProperty = DependencyProperty.Register(
|
|
"ImageHeight", typeof(double), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.Double0Box));
|
|
|
|
internal static readonly DependencyProperty ImageScaleProperty = DependencyProperty.Register(
|
|
"ImageScale", typeof(double), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.Double1Box, OnImageScaleChanged));
|
|
|
|
internal static readonly DependencyProperty ScaleStrProperty = DependencyProperty.Register(
|
|
"ScaleStr", typeof(string), typeof(ImageViewer), new PropertyMetadata("100%"));
|
|
|
|
internal static readonly DependencyProperty ImageRotateProperty = DependencyProperty.Register(
|
|
"ImageRotate", typeof(double), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.Double0Box));
|
|
|
|
internal static readonly DependencyProperty ShowSmallImgInternalProperty = DependencyProperty.Register(
|
|
"ShowSmallImgInternal", typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
|
|
|
|
public bool IsFullScreen
|
|
{
|
|
get => (bool)GetValue(IsFullScreenProperty);
|
|
set => SetValue(IsFullScreenProperty, value);
|
|
}
|
|
|
|
public bool ShowImgMap
|
|
{
|
|
get => (bool)GetValue(ShowImgMapProperty);
|
|
set => SetValue(ShowImgMapProperty, value);
|
|
}
|
|
|
|
public BitmapFrame ImageSource
|
|
{
|
|
get => (BitmapFrame)GetValue(ImageSourceProperty);
|
|
set => SetValue(ImageSourceProperty, value);
|
|
}
|
|
|
|
internal object ImageContent
|
|
{
|
|
get => GetValue(ImageContentProperty);
|
|
set => SetValue(ImageContentProperty, value);
|
|
}
|
|
|
|
internal string ImgPath
|
|
{
|
|
get => (string)GetValue(ImgPathProperty);
|
|
set => SetValue(ImgPathProperty, value);
|
|
}
|
|
|
|
internal long ImgSize
|
|
{
|
|
get => (long)GetValue(ImgSizeProperty);
|
|
set => SetValue(ImgSizeProperty, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 是否显示全屏按钮
|
|
/// </summary>
|
|
internal bool ShowFullScreenButton
|
|
{
|
|
get => (bool)GetValue(ShowFullScreenButtonProperty);
|
|
set => SetValue(ShowFullScreenButtonProperty, value);
|
|
}
|
|
|
|
internal Thickness ImageMargin
|
|
{
|
|
get => (Thickness)GetValue(ImageMarginProperty);
|
|
set => SetValue(ImageMarginProperty, value);
|
|
}
|
|
|
|
internal double ImageWidth
|
|
{
|
|
get => (double)GetValue(ImageWidthProperty);
|
|
set => SetValue(ImageWidthProperty, value);
|
|
}
|
|
|
|
internal double ImageHeight
|
|
{
|
|
get => (double)GetValue(ImageHeightProperty);
|
|
set => SetValue(ImageHeightProperty, value);
|
|
}
|
|
|
|
internal double ImageScale
|
|
{
|
|
get => (double)GetValue(ImageScaleProperty);
|
|
set => SetValue(ImageScaleProperty, value);
|
|
}
|
|
|
|
internal string ScaleStr
|
|
{
|
|
get => (string)GetValue(ScaleStrProperty);
|
|
set => SetValue(ScaleStrProperty, value);
|
|
}
|
|
|
|
internal double ImageRotate
|
|
{
|
|
get => (double)GetValue(ImageRotateProperty);
|
|
set => SetValue(ImageRotateProperty, value);
|
|
}
|
|
|
|
internal bool ShowSmallImgInternal
|
|
{
|
|
get => (bool)GetValue(ShowSmallImgInternalProperty);
|
|
set => SetValue(ShowSmallImgInternalProperty, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 图片原始宽度
|
|
/// </summary>
|
|
private double ImageOriWidth { get; set; }
|
|
|
|
/// <summary>
|
|
/// 图片原始高度
|
|
/// </summary>
|
|
private double ImageOriHeight { get; set; }
|
|
|
|
/// <summary>
|
|
/// 关闭按钮是否显示中
|
|
/// </summary>
|
|
internal bool ShowCloseButton
|
|
{
|
|
get => (bool)GetValue(ShowCloseButtonProperty);
|
|
set => SetValue(ShowCloseButtonProperty, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 底部BorderBottom(包含一些图片操作)是否显示中
|
|
/// </summary>
|
|
internal bool ShowBorderBottom
|
|
{
|
|
get => _showBorderBottom;
|
|
set
|
|
{
|
|
if (_showBorderBottom == value) return;
|
|
_borderBottom?.BeginAnimation(OpacityProperty,
|
|
value ? AnimationHelper.CreateAnimation(1, 100) : AnimationHelper.CreateAnimation(0, 400));
|
|
_showBorderBottom = value;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
public override void OnApplyTemplate()
|
|
{
|
|
if (_imageMain != null) _imageMain.MouseLeftButtonDown -= ImageMain_OnMouseLeftButtonDown;
|
|
|
|
if (_canvasSmallImg != null)
|
|
{
|
|
_canvasSmallImg.MouseLeftButtonDown -= CanvasSmallImg_OnMouseLeftButtonDown;
|
|
_canvasSmallImg.MouseLeftButtonUp -= CanvasSmallImg_OnMouseLeftButtonUp;
|
|
_canvasSmallImg.MouseMove -= CanvasSmallImg_OnMouseMove;
|
|
_canvasSmallImg.MouseLeave -= CanvasSmallImg_OnMouseLeave;
|
|
}
|
|
|
|
base.OnApplyTemplate();
|
|
|
|
_panelMain = GetTemplateChild(ElementPanelMain) as Panel;
|
|
_canvasSmallImg = GetTemplateChild(ElementCanvasSmallImg) as Canvas;
|
|
_borderMove = GetTemplateChild(ElementBorderMove) as Border;
|
|
_imageMain = GetTemplateChild(ElementImageMain) as Image;
|
|
_borderBottom = GetTemplateChild(ElementBorderBottom) as Border;
|
|
|
|
if (_imageMain != null)
|
|
{
|
|
var t = new RotateTransform();
|
|
BindingOperations.SetBinding(t, RotateTransform.AngleProperty, new Binding(ImageRotateProperty.Name) { Source = this });
|
|
_imageMain.LayoutTransform = t;
|
|
_imageMain.MouseLeftButtonDown += ImageMain_OnMouseLeftButtonDown;
|
|
}
|
|
|
|
if (_canvasSmallImg != null)
|
|
{
|
|
_canvasSmallImg.MouseLeftButtonDown += CanvasSmallImg_OnMouseLeftButtonDown;
|
|
_canvasSmallImg.MouseLeftButtonUp += CanvasSmallImg_OnMouseLeftButtonUp;
|
|
_canvasSmallImg.MouseMove += CanvasSmallImg_OnMouseMove;
|
|
_canvasSmallImg.MouseLeave += CanvasSmallImg_OnMouseLeave;
|
|
}
|
|
|
|
Init();
|
|
}
|
|
|
|
private static void OnImageScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
if (d is ImageViewer imageViewer && e.NewValue is double newValue)
|
|
{
|
|
imageViewer.ImageWidth = imageViewer.ImageOriWidth * newValue;
|
|
imageViewer.ImageHeight = imageViewer.ImageOriHeight * newValue;
|
|
imageViewer.ScaleStr = $"{newValue * 100:#0}%";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 初始化
|
|
/// </summary>
|
|
private void Init()
|
|
{
|
|
if (ImageSource == null) return;
|
|
|
|
double width;
|
|
double height;
|
|
|
|
if (!_isOblique)
|
|
{
|
|
width = ImageSource.Width;
|
|
height = ImageSource.Height;
|
|
}
|
|
else
|
|
{
|
|
width = ImageSource.Height;
|
|
height = ImageSource.Width;
|
|
}
|
|
|
|
ImageWidth = width;
|
|
ImageHeight = height;
|
|
ImageOriWidth = width;
|
|
ImageOriHeight = height;
|
|
_scaleInternalWidth = ImageOriWidth * ScaleInternal;
|
|
_scaleInternalHeight = ImageOriHeight * ScaleInternal;
|
|
|
|
if (Math.Abs(height - 0) < 0.001 || Math.Abs(width - 0) < 0.001)
|
|
{
|
|
MessageBox.Show(Lang.ErrorImgSize);
|
|
return;
|
|
}
|
|
|
|
_imgWidHeiScale = width / height;
|
|
Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
|
var scaleWindow = DesiredSize.Width / DesiredSize.Height;
|
|
if (_imgWidHeiScale > scaleWindow)
|
|
{
|
|
if (width > DesiredSize.Width)
|
|
ImageScale = DesiredSize.Width / width;
|
|
}
|
|
else if (height > DesiredSize.Height)
|
|
{
|
|
ImageScale = DesiredSize.Height / height;
|
|
}
|
|
else
|
|
{
|
|
ImageScale = 1;
|
|
}
|
|
|
|
ImageMargin = new Thickness((DesiredSize.Width - ImageWidth) / 2, (DesiredSize.Height - ImageHeight) / 2, 0, 0);
|
|
|
|
_imgActualScale = ImageScale;
|
|
_imgActualMargin = ImageMargin;
|
|
|
|
InitBorderSmall();
|
|
}
|
|
|
|
private void ButtonActual_OnClick(object sender, RoutedEventArgs e)
|
|
{
|
|
var scaleAnimation = AnimationHelper.CreateAnimation(1);
|
|
scaleAnimation.FillBehavior = FillBehavior.Stop;
|
|
_imgActualScale = 1;
|
|
scaleAnimation.Completed += (s, e1) =>
|
|
{
|
|
ImageScale = 1;
|
|
_canMoveX = ImageWidth > ActualWidth;
|
|
_canMoveY = ImageHeight > ActualHeight;
|
|
BorderSmallShowSwitch();
|
|
};
|
|
var thickness = new Thickness((ActualWidth - ImageOriWidth) / 2, (ActualHeight - ImageOriHeight) / 2, 0, 0);
|
|
var marginAnimation = AnimationHelper.CreateAnimation(thickness);
|
|
marginAnimation.FillBehavior = FillBehavior.Stop;
|
|
_imgActualMargin = thickness;
|
|
marginAnimation.Completed += (s, e1) => { ImageMargin = thickness; };
|
|
|
|
BeginAnimation(ImageScaleProperty, scaleAnimation);
|
|
BeginAnimation(ImageMarginProperty, marginAnimation);
|
|
}
|
|
|
|
private void ButtonReduce_OnClick(object sender, RoutedEventArgs e) => ScaleImg(false);
|
|
|
|
private void ButtonEnlarge_OnClick(object sender, RoutedEventArgs e) => ScaleImg(true);
|
|
|
|
private void ButtonRotateLeft_OnClick(object sender, RoutedEventArgs e) => RotateImg(_imgActualRotate - 90);
|
|
|
|
private void ButtonRotateRight_OnClick(object sender, RoutedEventArgs e) => RotateImg(_imgActualRotate + 90);
|
|
|
|
private void ButtonSave_OnClick(object sender, RoutedEventArgs e)
|
|
{
|
|
if (ImageSource == null) return;
|
|
SaveFileDialog.FileName = $"{DateTime.Now:yyyy-M-d-h-m-s.fff}";
|
|
if (SaveFileDialog.ShowDialog() == true)
|
|
{
|
|
var path = SaveFileDialog.FileName;
|
|
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write))
|
|
{
|
|
var encoder = new PngBitmapEncoder();
|
|
encoder.Frames.Add(BitmapFrame.Create(ImageSource));
|
|
encoder.Save(fileStream);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ButtonWindowsOpen_OnClick(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
Process.Start(ImgPath);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
MessageBox.Show(exception.Message);
|
|
}
|
|
}
|
|
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
|
{
|
|
base.OnMouseMove(e);
|
|
MoveImg();
|
|
}
|
|
|
|
protected override void OnMouseLeave(MouseEventArgs e)
|
|
{
|
|
base.OnMouseLeave(e);
|
|
_imgIsMouseLeftButtonDown = false;
|
|
ShowBorderBottom = false;
|
|
}
|
|
|
|
protected override void OnMouseWheel(MouseWheelEventArgs e)
|
|
{
|
|
base.OnMouseWheel(e);
|
|
ScaleImg(e.Delta > 0);
|
|
}
|
|
|
|
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
|
|
{
|
|
base.OnRenderSizeChanged(sizeInfo);
|
|
|
|
OnRenderSizeChanged();
|
|
}
|
|
|
|
private void OnRenderSizeChanged()
|
|
{
|
|
if (ImageWidth < 0.001 || ImageHeight < 0.001) return;
|
|
|
|
_canMoveX = true;
|
|
_canMoveY = true;
|
|
|
|
var marginX = ImageMargin.Left;
|
|
var marginY = ImageMargin.Top;
|
|
|
|
if (ImageWidth <= ActualWidth)
|
|
{
|
|
_canMoveX = false;
|
|
marginX = (ActualWidth - ImageWidth) / 2;
|
|
}
|
|
|
|
if (ImageHeight <= ActualHeight)
|
|
{
|
|
_canMoveY = false;
|
|
marginY = (ActualHeight - ImageHeight) / 2;
|
|
}
|
|
|
|
ImageMargin = new Thickness(marginX, marginY, 0, 0);
|
|
_imgActualMargin = ImageMargin;
|
|
|
|
BorderSmallShowSwitch();
|
|
_imgSmallMouseDownMargin = _borderMove.Margin;
|
|
MoveSmallImg(_imgSmallMouseDownMargin.Left, _imgSmallMouseDownMargin.Top);
|
|
}
|
|
|
|
private void ImageMain_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
_imgMouseDownPoint = Mouse.GetPosition(_panelMain);
|
|
_imgMouseDownMargin = ImageMargin;
|
|
_imgIsMouseLeftButtonDown = true;
|
|
}
|
|
|
|
protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
|
|
{
|
|
base.OnPreviewMouseLeftButtonUp(e);
|
|
_imgIsMouseLeftButtonDown = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 右下角小图片显示切换
|
|
/// </summary>
|
|
private void BorderSmallShowSwitch()
|
|
{
|
|
if (_canMoveX || _canMoveY)
|
|
{
|
|
if (!_borderSmallIsLoaded)
|
|
{
|
|
_canvasSmallImg.Background = new VisualBrush(_imageMain);
|
|
InitBorderSmall();
|
|
_borderSmallIsLoaded = true;
|
|
}
|
|
|
|
ShowSmallImgInternal = true;
|
|
UpdateBorderSmall();
|
|
}
|
|
else
|
|
{
|
|
ShowSmallImgInternal = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 初始化右下角小图片
|
|
/// </summary>
|
|
private void InitBorderSmall()
|
|
{
|
|
var scaleWindow = _canvasSmallImg.MaxWidth / _canvasSmallImg.MaxHeight;
|
|
if (_imgWidHeiScale > scaleWindow)
|
|
{
|
|
_canvasSmallImg.Width = _canvasSmallImg.MaxWidth;
|
|
_canvasSmallImg.Height = _canvasSmallImg.Width / _imgWidHeiScale;
|
|
}
|
|
else
|
|
{
|
|
_canvasSmallImg.Width = _canvasSmallImg.MaxHeight * _imgWidHeiScale;
|
|
_canvasSmallImg.Height = _canvasSmallImg.MaxHeight;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新右下角小图片
|
|
/// </summary>
|
|
private void UpdateBorderSmall()
|
|
{
|
|
if (!ShowSmallImgInternal) return;
|
|
|
|
var widthMin = Math.Min(ImageWidth, ActualWidth);
|
|
var heightMin = Math.Min(ImageHeight, ActualHeight);
|
|
|
|
_borderMove.Width = widthMin / ImageWidth * _canvasSmallImg.Width;
|
|
_borderMove.Height = heightMin / ImageHeight * _canvasSmallImg.Height;
|
|
|
|
var marginX = -ImageMargin.Left / ImageWidth * _canvasSmallImg.Width;
|
|
var marginY = -ImageMargin.Top / ImageHeight * _canvasSmallImg.Height;
|
|
|
|
var marginXMax = _canvasSmallImg.Width - _borderMove.Width;
|
|
var marginYMax = _canvasSmallImg.Height - _borderMove.Height;
|
|
|
|
marginX = Math.Max(0, marginX);
|
|
marginX = Math.Min(marginXMax, marginX);
|
|
marginY = Math.Max(0, marginY);
|
|
marginY = Math.Min(marginYMax, marginY);
|
|
|
|
_borderMove.Margin = new Thickness(marginX, marginY, 0, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 缩放图片
|
|
/// </summary>
|
|
/// <param name="isEnlarge"></param>
|
|
private void ScaleImg(bool isEnlarge)
|
|
{
|
|
if (Mouse.LeftButton == MouseButtonState.Pressed) return;
|
|
var oldImageWidth = ImageWidth;
|
|
var olgImageHeight = ImageHeight;
|
|
|
|
var tempScale = isEnlarge ? _imgActualScale + ScaleInternal : _imgActualScale - ScaleInternal;
|
|
if (Math.Abs(tempScale) < ScaleInternal || Math.Abs(tempScale - 50) < 0.001)
|
|
return;
|
|
|
|
ImageScale = tempScale;
|
|
|
|
var posCanvas = Mouse.GetPosition(_panelMain);
|
|
var posImg = new Point(posCanvas.X - _imgActualMargin.Left, posCanvas.Y - _imgActualMargin.Top);
|
|
|
|
var marginX = .5 * _scaleInternalWidth;
|
|
var marginY = .5 * _scaleInternalHeight;
|
|
|
|
if (ImageWidth > ActualWidth)
|
|
{
|
|
_canMoveX = true;
|
|
if (ImageHeight > ActualHeight)
|
|
{
|
|
_canMoveY = true;
|
|
marginX = posImg.X / oldImageWidth * _scaleInternalWidth;
|
|
marginY = posImg.Y / olgImageHeight * _scaleInternalHeight;
|
|
}
|
|
else
|
|
{
|
|
_canMoveY = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_canMoveY = ImageHeight > ActualHeight;
|
|
_canMoveX = false;
|
|
}
|
|
|
|
Thickness thickness;
|
|
if (isEnlarge)
|
|
{
|
|
thickness = new Thickness(_imgActualMargin.Left - marginX, _imgActualMargin.Top - marginY, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
var marginActualX = _imgActualMargin.Left + marginX;
|
|
var marginActualY = _imgActualMargin.Top + marginY;
|
|
var subX = ImageWidth - ActualWidth;
|
|
var subY = ImageHeight - ActualHeight;
|
|
|
|
var right = Math.Abs(_borderMove.Width - _canvasSmallImg.ActualWidth + _borderMove.Margin.Left);
|
|
var top = Math.Abs(_borderMove.Height - _canvasSmallImg.ActualHeight + _borderMove.Margin.Top);
|
|
if (Math.Abs(ImageMargin.Left) < 0.001 || right < 0.001)
|
|
marginActualX = _imgActualMargin.Left + _borderMove.Margin.Left /
|
|
(_canvasSmallImg.ActualWidth - _borderMove.Width) * _scaleInternalWidth;
|
|
if (Math.Abs(ImageMargin.Top) < 0.001 || top < 0.001)
|
|
marginActualY = _imgActualMargin.Top + _borderMove.Margin.Top /
|
|
(_canvasSmallImg.ActualHeight - _borderMove.Height) * _scaleInternalHeight;
|
|
if (subX < 0.001) marginActualX = (ActualWidth - ImageWidth) / 2;
|
|
if (subY < 0.001) marginActualY = (ActualHeight - ImageHeight) / 2;
|
|
thickness = new Thickness(marginActualX, marginActualY, 0, 0);
|
|
}
|
|
|
|
ImageMargin = thickness;
|
|
_imgActualScale = tempScale;
|
|
_imgActualMargin = thickness;
|
|
BorderSmallShowSwitch();
|
|
|
|
_imgSmallMouseDownMargin = _borderMove.Margin;
|
|
MoveSmallImg(_imgSmallMouseDownMargin.Left, _imgSmallMouseDownMargin.Top);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 旋转图片
|
|
/// </summary>
|
|
/// <param name="rotate"></param>
|
|
private void RotateImg(double rotate)
|
|
{
|
|
_imgActualRotate = rotate;
|
|
|
|
_isOblique = ((int)_imgActualRotate - 90) % 180 == 0;
|
|
ShowSmallImgInternal = false;
|
|
Init();
|
|
InitBorderSmall();
|
|
|
|
var animation = AnimationHelper.CreateAnimation(rotate);
|
|
animation.Completed += (s, e1) => { ImageRotate = rotate; };
|
|
animation.FillBehavior = FillBehavior.Stop;
|
|
BeginAnimation(ImageRotateProperty, animation);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移动图片
|
|
/// </summary>
|
|
private void MoveImg()
|
|
{
|
|
_imgCurrentPoint = Mouse.GetPosition(_panelMain);
|
|
ShowCloseButton = _imgCurrentPoint.Y < 200;
|
|
ShowBorderBottom = _imgCurrentPoint.Y > ActualHeight - 200;
|
|
|
|
if (_imgIsMouseLeftButtonDown)
|
|
{
|
|
var subX = _imgCurrentPoint.X - _imgMouseDownPoint.X;
|
|
var subY = _imgCurrentPoint.Y - _imgMouseDownPoint.Y;
|
|
|
|
var marginX = _imgMouseDownMargin.Left;
|
|
if (ImageWidth > ActualWidth)
|
|
{
|
|
marginX = _imgMouseDownMargin.Left + subX;
|
|
if (marginX >= 0)
|
|
marginX = 0;
|
|
else if (-marginX + ActualWidth >= ImageWidth) marginX = ActualWidth - ImageWidth;
|
|
_canMoveX = true;
|
|
}
|
|
|
|
var marginY = _imgMouseDownMargin.Top;
|
|
if (ImageHeight > ActualHeight)
|
|
{
|
|
marginY = _imgMouseDownMargin.Top + subY;
|
|
if (marginY >= 0)
|
|
marginY = 0;
|
|
else if (-marginY + ActualHeight >= ImageHeight) marginY = ActualHeight - ImageHeight;
|
|
_canMoveY = true;
|
|
}
|
|
|
|
ImageMargin = new Thickness(marginX, marginY, 0, 0);
|
|
_imgActualMargin = ImageMargin;
|
|
|
|
UpdateBorderSmall();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移动小图片
|
|
/// </summary>
|
|
private void MoveSmallImg()
|
|
{
|
|
if (_imgSmallIsMouseLeftButtonDown)
|
|
{
|
|
_imgSmallCurrentPoint = Mouse.GetPosition(_canvasSmallImg);
|
|
|
|
var subX = _imgSmallCurrentPoint.X - _imgSmallMouseDownPoint.X;
|
|
var subY = _imgSmallCurrentPoint.Y - _imgSmallMouseDownPoint.Y;
|
|
|
|
var marginX = _imgSmallMouseDownMargin.Left + subX;
|
|
var marginY = _imgSmallMouseDownMargin.Top + subY;
|
|
|
|
MoveSmallImg(marginX, marginY);
|
|
}
|
|
}
|
|
|
|
private void MoveSmallImg(double marginX, double marginY)
|
|
{
|
|
if (marginX < 0)
|
|
marginX = 0;
|
|
else if (marginX + _borderMove.Width >= _canvasSmallImg.Width)
|
|
marginX = _canvasSmallImg.Width - _borderMove.Width;
|
|
if (marginY < 0)
|
|
marginY = 0;
|
|
else if (marginY + _borderMove.Height >= _canvasSmallImg.Height)
|
|
marginY = _canvasSmallImg.Height - _borderMove.Height;
|
|
_borderMove.Margin = new Thickness(marginX, marginY, 0, 0);
|
|
|
|
var marginActualX = (ActualWidth - ImageWidth) / 2;
|
|
var marginActualY = (ActualHeight - ImageHeight) / 2;
|
|
|
|
if (_canMoveX) marginActualX = -marginX / _canvasSmallImg.Width * ImageWidth;
|
|
if (_canMoveY) marginActualY = -marginY / _canvasSmallImg.Height * ImageHeight;
|
|
|
|
ImageMargin = new Thickness(marginActualX, marginActualY, 0, 0);
|
|
_imgActualMargin = ImageMargin;
|
|
}
|
|
|
|
private void CanvasSmallImg_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
_imgSmallMouseDownPoint = Mouse.GetPosition(_canvasSmallImg);
|
|
_imgSmallMouseDownMargin = _borderMove.Margin;
|
|
_imgSmallIsMouseLeftButtonDown = true;
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void CanvasSmallImg_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) => _imgSmallIsMouseLeftButtonDown = false;
|
|
|
|
private void CanvasSmallImg_OnMouseMove(object sender, MouseEventArgs e) => MoveSmallImg();
|
|
|
|
private void CanvasSmallImg_OnMouseLeave(object sender, MouseEventArgs e) => _imgSmallIsMouseLeftButtonDown = false;
|
|
}
|
|
} |