using System;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
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";
///
/// 缩放比间隔
///
private const double ScaleInternal = 0.2;
#endregion Constants
#region Data
///
/// 图片保存对话框
///
private static readonly SaveFileDialog SaveFileDialog = new()
{
Filter = $"{Lang.PngImg}|*.png"
};
private Panel _panelMain;
private Canvas _canvasSmallImg;
private Border _borderMove;
private Border _borderBottom;
private Image _imageMain;
///
/// 右下角小图片是否加载过
///
private bool _borderSmallIsLoaded;
///
/// 图片是否可以在x轴方向移动
///
private bool _canMoveX;
///
/// 图片是否可以在y轴方向移动
///
private bool _canMoveY;
///
/// 图片实际位置
///
private Thickness _imgActualMargin;
///
/// 图片实际旋转角度
///
private double _imgActualRotate;
///
/// 图片实际旋缩放比
///
private double _imgActualScale = 1;
///
/// 在图片上鼠标移动时的即时位置
///
private Point _imgCurrentPoint;
///
/// 鼠标是否在图片上按下
///
private bool _imgIsMouseDown;
///
/// 在图片上按下时图片的位置
///
private Thickness _imgMouseDownMargin;
///
/// 在图片上按下时鼠标的位置
///
private Point _imgMouseDownPoint;
///
/// 在小图片上鼠标移动时的即时位置
///
private Point _imgSmallCurrentPoint;
///
/// 鼠标是否在小图片上按下
///
private bool _imgSmallIsMouseDown;
///
/// 在小图片上按下时图片的位置
///
private Thickness _imgSmallMouseDownMargin;
///
/// 在小图片上按下时鼠标的位置
///
private Point _imgSmallMouseDownPoint;
///
/// 图片长宽比
///
private double _imgWidHeiScale;
///
/// 图片是否倾斜
///
private bool _isOblique;
///
/// 缩放高度间隔
///
private double _scaleInternalHeight;
///
/// 缩放宽度间隔
///
private double _scaleInternalWidth;
///
/// 底部BorderBottom(包含一些图片操作)是否显示中
///
private bool _showBorderBottom;
private DispatcherTimer _dispatcher;
private bool _isLoaded;
private MouseBinding _mouseMoveBinding;
private ImageBrowser _imageBrowser;
#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));
CommandBindings.Add(new CommandBinding(ControlCommands.MouseMove, ImageMain_OnMouseDown));
OnMoveGestureChanged(MoveGesture);
Loaded += (s, e) =>
{
_isLoaded = true;
Init();
};
}
///
/// 带一个图片Uri的构造函数
///
///
public ImageViewer(Uri uri) : this()
{
Uri = uri;
}
///
/// 带一个图片路径的构造函数
///
///
public ImageViewer(string path) : this(new Uri(path))
{
}
#endregion
#region Properties
public static readonly DependencyProperty ShowImgMapProperty = DependencyProperty.Register(
nameof(ShowImgMap), typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register(
nameof(ImageSource), typeof(BitmapFrame), typeof(ImageViewer), new PropertyMetadata(default(BitmapFrame), OnImageSourceChanged));
public static readonly DependencyProperty UriProperty = DependencyProperty.Register(
nameof(Uri), typeof(Uri), typeof(ImageViewer), new PropertyMetadata(default(Uri), OnUriChanged));
public static readonly DependencyProperty ShowToolBarProperty = DependencyProperty.Register(
nameof(ShowToolBar), typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.TrueBox));
public static readonly DependencyProperty IsFullScreenProperty = DependencyProperty.Register(
nameof(IsFullScreen), typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
public static readonly DependencyProperty MoveGestureProperty = DependencyProperty.Register(
nameof(MoveGesture), typeof(MouseGesture), typeof(ImageViewer), new UIPropertyMetadata(new MouseGesture(MouseAction.LeftClick), OnMoveGestureChanged));
internal static readonly DependencyProperty ImgPathProperty = DependencyProperty.Register(
nameof(ImgPath), typeof(string), typeof(ImageViewer), new PropertyMetadata(default(string)));
internal static readonly DependencyProperty ImgSizeProperty = DependencyProperty.Register(
nameof(ImgSize), typeof(long), typeof(ImageViewer), new PropertyMetadata(-1L));
internal static readonly DependencyProperty ShowFullScreenButtonProperty = DependencyProperty.Register(
nameof(ShowFullScreenButton), typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
internal static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register(
nameof(ShowCloseButton), typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
internal static readonly DependencyProperty ImageContentProperty = DependencyProperty.Register(
nameof(ImageContent), typeof(object), typeof(ImageViewer), new PropertyMetadata(default(object)));
internal static readonly DependencyProperty ImageMarginProperty = DependencyProperty.Register(
nameof(ImageMargin), typeof(Thickness), typeof(ImageViewer), new PropertyMetadata(default(Thickness)));
internal static readonly DependencyProperty ImageWidthProperty = DependencyProperty.Register(
nameof(ImageWidth), typeof(double), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.Double0Box));
internal static readonly DependencyProperty ImageHeightProperty = DependencyProperty.Register(
nameof(ImageHeight), typeof(double), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.Double0Box));
internal static readonly DependencyProperty ImageScaleProperty = DependencyProperty.Register(
nameof(ImageScale), typeof(double), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.Double1Box, OnImageScaleChanged));
internal static readonly DependencyProperty ScaleStrProperty = DependencyProperty.Register(
nameof(ScaleStr), typeof(string), typeof(ImageViewer), new PropertyMetadata("100%"));
internal static readonly DependencyProperty ImageRotateProperty = DependencyProperty.Register(
nameof(ImageRotate), typeof(double), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.Double0Box));
internal static readonly DependencyProperty ShowSmallImgInternalProperty = DependencyProperty.Register(
nameof(ShowSmallImgInternal), typeof(bool), typeof(ImageViewer), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsFullScreen
{
get => (bool) GetValue(IsFullScreenProperty);
set => SetValue(IsFullScreenProperty, ValueBoxes.BooleanBox(value));
}
[ValueSerializer(typeof(MouseGestureValueSerializer))]
[TypeConverter(typeof(MouseGestureConverter))]
public MouseGesture MoveGesture
{
get => (MouseGesture) GetValue(MoveGestureProperty);
set => SetValue(MoveGestureProperty, value);
}
public bool ShowImgMap
{
get => (bool) GetValue(ShowImgMapProperty);
set => SetValue(ShowImgMapProperty, ValueBoxes.BooleanBox(value));
}
public BitmapFrame ImageSource
{
get => (BitmapFrame) GetValue(ImageSourceProperty);
set => SetValue(ImageSourceProperty, value);
}
public Uri Uri
{
get => (Uri) GetValue(UriProperty);
set => SetValue(UriProperty, value);
}
public bool ShowToolBar
{
get => (bool) GetValue(ShowToolBarProperty);
set => SetValue(ShowToolBarProperty, ValueBoxes.BooleanBox(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);
}
///
/// 是否显示全屏按钮
///
internal bool ShowFullScreenButton
{
get => (bool) GetValue(ShowFullScreenButtonProperty);
set => SetValue(ShowFullScreenButtonProperty, ValueBoxes.BooleanBox(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, ValueBoxes.BooleanBox(value));
}
///
/// 图片原始宽度
///
private double ImageOriWidth { get; set; }
///
/// 图片原始高度
///
private double ImageOriHeight { get; set; }
///
/// 关闭按钮是否显示中
///
internal bool ShowCloseButton
{
get => (bool) GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value));
}
///
/// 底部BorderBottom(包含一些图片操作)是否显示中
///
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 (_canvasSmallImg != null)
{
_canvasSmallImg.MouseLeftButtonDown -= CanvasSmallImg_OnMouseLeftButtonDown;
_canvasSmallImg.MouseLeftButtonUp -= CanvasSmallImg_OnMouseLeftButtonUp;
_canvasSmallImg.MouseMove -= CanvasSmallImg_OnMouseMove;
}
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;
}
if (_canvasSmallImg != null)
{
_canvasSmallImg.MouseLeftButtonDown += CanvasSmallImg_OnMouseLeftButtonDown;
_canvasSmallImg.MouseLeftButtonUp += CanvasSmallImg_OnMouseLeftButtonUp;
_canvasSmallImg.MouseMove += CanvasSmallImg_OnMouseMove;
}
_borderSmallIsLoaded = false;
}
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}%";
}
}
///
/// 初始化
///
private void Init()
{
if (ImageSource == null || !_isLoaded) return;
if (ImageSource.IsDownloading)
{
_dispatcher = new DispatcherTimer(DispatcherPriority.ApplicationIdle)
{
Interval = TimeSpan.FromSeconds(1)
};
_dispatcher.Tick += Dispatcher_Tick;
_dispatcher.Start();
return;
}
double width;
double height;
if (!_isOblique)
{
width = ImageSource.PixelWidth;
height = ImageSource.PixelHeight;
}
else
{
width = ImageSource.PixelHeight;
height = ImageSource.PixelWidth;
}
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;
var scaleWindow = ActualWidth / ActualHeight;
ImageScale = 1;
if (_imgWidHeiScale > scaleWindow)
{
if (width > ActualWidth)
{
ImageScale = ActualWidth / width;
}
}
else if (height > ActualHeight)
{
ImageScale = ActualHeight / height;
}
ImageMargin = new Thickness((ActualWidth - ImageWidth) / 2, (ActualHeight - ImageHeight) / 2, 0, 0);
_imgActualScale = ImageScale;
_imgActualMargin = ImageMargin;
InitBorderSmall();
}
private void Dispatcher_Tick(object sender, EventArgs e)
{
if (_dispatcher == null) return;
if (ImageSource == null || !_isLoaded)
{
_dispatcher.Stop();
_dispatcher.Tick -= Dispatcher_Tick;
_dispatcher = null;
return;
}
if (!ImageSource.IsDownloading)
{
_dispatcher.Stop();
_dispatcher.Tick -= Dispatcher_Tick;
_dispatcher = null;
Init();
}
}
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)
{
if (Uri is { } uri)
{
_imageBrowser?.Close();
_imageBrowser = new ImageBrowser(uri);
_imageBrowser.Show();
}
}
protected override void OnMouseMove(MouseEventArgs e) => MoveImg();
protected override void OnMouseLeave(MouseEventArgs e) => ShowBorderBottom = false;
protected override void OnMouseWheel(MouseWheelEventArgs 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_OnMouseDown(object sender, ExecutedRoutedEventArgs e)
{
_imgMouseDownPoint = Mouse.GetPosition(_panelMain);
_imgMouseDownMargin = ImageMargin;
_imgIsMouseDown = true;
}
protected override void OnPreviewMouseUp(MouseButtonEventArgs e) => _imgIsMouseDown = false;
///
/// 右下角小图片显示切换
///
private void BorderSmallShowSwitch()
{
if (_canMoveX || _canMoveY)
{
if (!_borderSmallIsLoaded)
{
_canvasSmallImg.Background = new VisualBrush(_imageMain);
InitBorderSmall();
_borderSmallIsLoaded = true;
}
ShowSmallImgInternal = true;
UpdateBorderSmall();
}
else
{
ShowSmallImgInternal = false;
}
}
///
/// 初始化右下角小图片
///
private void InitBorderSmall()
{
if (_canvasSmallImg == null) return;
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;
}
}
///
/// 更新右下角小图片
///
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);
}
///
/// 缩放图片
///
///
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)
{
tempScale = ScaleInternal;
}
else if (Math.Abs(tempScale) > 50)
{
tempScale = 50;
}
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);
}
///
/// 旋转图片
///
///
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);
}
private MouseButtonState GetMouseButtonState() => MoveGesture.MouseAction switch
{
MouseAction.LeftClick => Mouse.LeftButton,
MouseAction.RightClick => Mouse.RightButton,
MouseAction.MiddleClick => Mouse.MiddleButton,
_ => Mouse.LeftButton
};
///
/// 移动图片
///
private void MoveImg()
{
_imgCurrentPoint = Mouse.GetPosition(_panelMain);
ShowCloseButton = _imgCurrentPoint.Y < 200;
ShowBorderBottom = _imgCurrentPoint.Y > ActualHeight - 200;
if (GetMouseButtonState() == MouseButtonState.Released)
{
return;
}
if (_imgIsMouseDown)
{
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();
}
}
///
/// 移动小图片
///
private void MoveSmallImg()
{
if (!_imgSmallIsMouseDown)
{
return;
}
if (GetMouseButtonState() == MouseButtonState.Released)
{
return;
}
_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;
_imgSmallIsMouseDown = true;
e.Handled = true;
}
private void CanvasSmallImg_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) => _imgSmallIsMouseDown = false;
private void CanvasSmallImg_OnMouseMove(object sender, MouseEventArgs e) => MoveSmallImg();
private static void OnMoveGestureChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ImageViewer) d).OnMoveGestureChanged((MouseGesture) e.NewValue);
}
private void OnMoveGestureChanged(MouseGesture newValue)
{
InputBindings.Remove(_mouseMoveBinding);
_mouseMoveBinding = new MouseBinding(ControlCommands.MouseMove, newValue);
InputBindings.Add(_mouseMoveBinding);
}
private static void OnImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ImageViewer) d).OnImageSourceChanged();
}
private void OnImageSourceChanged()
{
Init();
}
private static void OnUriChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ImageViewer) d).OnUriChanged((Uri) e.NewValue);
}
private void OnUriChanged(Uri newValue)
{
if (newValue is not null)
{
ImageSource = GetBitmapFrame(newValue);
ImgPath = newValue.AbsolutePath;
if (File.Exists(ImgPath))
{
ImgSize = new FileInfo(ImgPath).Length;
}
}
else
{
ImageSource = null;
ImgPath = string.Empty;
}
static BitmapFrame GetBitmapFrame(Uri source)
{
try
{
return BitmapFrame.Create(source);
}
catch
{
return null;
}
}
}
}