From d4220a60a776bad66423f4736a8d65ce0aea5631 Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Mon, 27 Aug 2018 11:29:13 +0800 Subject: [PATCH] update to v1.1.0 --- ChangeLog.txt | 10 + .../Controls/Window/ImageBrowser.xaml | 81 ++ .../Controls/Window/ImageBrowser.xaml.cs | 829 ++++++++++++++++++ HandyControl/Controls/Window/PopupWindow.xaml | 59 ++ .../Controls/Window/PopupWindow.xaml.cs | 171 ++++ .../Controls/Window/WindowBorderless.cs | 254 ++++++ HandyControl/HandyControl.csproj | 23 + HandyControl/Properties/AssemblyInfo.cs | 4 +- HandyControl/Themes/Basic/Geometries.xaml | 12 + .../Styles/Base/ContextMenuBaseStyle.xaml | 218 +++++ HandyControl/Themes/Styles/ContextMenu.xaml | 14 + HandyControl/Themes/Styles/Style.xaml | 2 +- HandyControl/Themes/Styles/Window.xaml | 121 ++- HandyControl/Tools/ArithmeticHelper.cs | 21 + HandyControlDemo/HandyControlDemo.csproj | 3 + HandyControlDemo/MainWindow.xaml | 64 +- HandyControlDemo/MainWindow.xaml.cs | 9 +- HandyControlDemo/Resources/icon-white.png | Bin 0 -> 16561 bytes 18 files changed, 1866 insertions(+), 29 deletions(-) create mode 100644 ChangeLog.txt create mode 100644 HandyControl/Controls/Window/ImageBrowser.xaml create mode 100644 HandyControl/Controls/Window/ImageBrowser.xaml.cs create mode 100644 HandyControl/Controls/Window/PopupWindow.xaml create mode 100644 HandyControl/Controls/Window/PopupWindow.xaml.cs create mode 100644 HandyControl/Controls/Window/WindowBorderless.cs create mode 100644 HandyControl/Themes/Styles/Base/ContextMenuBaseStyle.xaml create mode 100644 HandyControl/Themes/Styles/ContextMenu.xaml create mode 100644 HandyControlDemo/Resources/icon-white.png diff --git a/ChangeLog.txt b/ChangeLog.txt new file mode 100644 index 00000000..ca9d9848 --- /dev/null +++ b/ChangeLog.txt @@ -0,0 +1,10 @@ +2018.08.27 Version 1.1.0 + +* new controls + - add WindowBorderless + - add ImageBrowser + - add PopupWindow + +* new styles + - add Menu + - add Window \ No newline at end of file diff --git a/HandyControl/Controls/Window/ImageBrowser.xaml b/HandyControl/Controls/Window/ImageBrowser.xaml new file mode 100644 index 00000000..702febe9 --- /dev/null +++ b/HandyControl/Controls/Window/ImageBrowser.xaml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HandyControl/Controls/Window/ImageBrowser.xaml.cs b/HandyControl/Controls/Window/ImageBrowser.xaml.cs new file mode 100644 index 00000000..53660ea2 --- /dev/null +++ b/HandyControl/Controls/Window/ImageBrowser.xaml.cs @@ -0,0 +1,829 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using HandyControl.Tools; +using Microsoft.Win32; + +// ReSharper disable once CheckNamespace +namespace HandyControl.Controls +{ + /// + /// 图片浏览器 + /// + public partial class ImageBrowser + { + /// + /// 缩放比间隔 + /// + private const double ScaleInternal = 0.2; + + static ImageBrowser() + { + IsFullScreenProperty.AddOwner(typeof(ImageBrowser), new PropertyMetadata(default(bool))); + } + + private static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register( + "ImageSource", typeof(BitmapFrame), typeof(ImageBrowser), new PropertyMetadata(default(BitmapFrame))); + + private static readonly DependencyProperty ImageMarginProperty = DependencyProperty.Register( + "ImageMargin", typeof(Thickness), typeof(ImageBrowser), new PropertyMetadata(default(Thickness))); + + private static readonly DependencyProperty ImageWidthProperty = DependencyProperty.Register( + "ImageWidth", typeof(double), typeof(ImageBrowser), new PropertyMetadata(default(double))); + + private static readonly DependencyProperty ImageHeightProperty = DependencyProperty.Register( + "ImageHeight", typeof(double), typeof(ImageBrowser), new PropertyMetadata(default(double))); + + public static readonly DependencyProperty ImageScaleProperty = DependencyProperty.Register( + "ImageScale", typeof(double), typeof(ImageBrowser), new PropertyMetadata(1.0, OnImageScaleChanged)); + + private static readonly DependencyProperty ScaleStrProperty = DependencyProperty.Register( + "ScaleStr", typeof(string), typeof(ImageBrowser), new PropertyMetadata("100%")); + + private static readonly DependencyProperty ImageRotateProperty = DependencyProperty.Register( + "ImageRotate", typeof(double), typeof(ImageBrowser), new PropertyMetadata(default(double))); + + private static readonly DependencyProperty ShowSmallImgProperty = DependencyProperty.Register( + "ShowSmallImg", typeof(bool), typeof(ImageBrowser), new PropertyMetadata(false)); + + /// + /// 图片保存对话框 + /// + private static readonly SaveFileDialog SaveFileDialog = new SaveFileDialog + { + Filter = "PNG图片|*.png" + }; + + public static readonly DependencyProperty ImgPathProperty = DependencyProperty.Register( + "ImgPath", typeof(string), typeof(ImageBrowser), new PropertyMetadata(default(string))); + + public string ImgPath + { + get => (string)GetValue(ImgPathProperty); + set => SetValue(ImgPathProperty, value); + } + + public static readonly DependencyProperty ImgSizeProperty = DependencyProperty.Register( + "ImgSize", typeof(long), typeof(ImageBrowser), new PropertyMetadata(-1L)); + + public long ImgSize + { + get => (long)GetValue(ImgSizeProperty); + set => SetValue(ImgSizeProperty, value); + } + + /// + /// 右下角小图片是否加载过 + /// + private bool _borderSmallIsLoaded; + + /// + /// 图片实际位置 + /// + private Thickness _imgActualMargin; + + /// + /// 图片实际旋转角度 + /// + private double _imgActualRotate; + + /// + /// 图片实际旋缩放比 + /// + private double _imgActualScale = 1; + + /// + /// 在图片上鼠标移动时的即时位置 + /// + private Point _imgCurrentPoint; + + /// + /// 在小图片上鼠标移动时的即时位置 + /// + private Point _imgSmallCurrentPoint; + + /// + /// 鼠标是否在图片上按下左键 + /// + private bool _imgIsMouseLeftButtonDown; + + /// + /// 鼠标是否在小图片上按下左键 + /// + private bool _imgSmallIsMouseLeftButtonDown; + + /// + /// 在图片上按下时图片的位置 + /// + private Thickness _imgMouseDownMargin; + + /// + /// 在小图片上按下时图片的位置 + /// + private Thickness _imgSmallMouseDownMargin; + + /// + /// 在图片上按下时鼠标的位置 + /// + private Point _imgMouseDownPoint; + + /// + /// 在小图片上按下时鼠标的位置 + /// + private Point _imgSmallMouseDownPoint; + + /// + /// 图片长宽比 + /// + private double _imgWidHeiScale; + + /// + /// 是否已经初始化 + /// + private bool _isLoaded; + + /// + /// 缩放高度间隔 + /// + private double _scaleInternalHeight; + + /// + /// 缩放宽度间隔 + /// + private double _scaleInternalWidth; + + /// + /// 底部BorderBottom(包含一些图片操作)是否显示中 + /// + private bool _showBorderBottom; + + /// + /// 关闭按钮是否显示中 + /// + private bool _showCloseButton; + + /// + /// 图片是否可以在x轴方向移动 + /// + private bool _canMoveX; + + /// + /// 图片是否可以在y轴方向移动 + /// + private bool _canMoveY; + + /// + /// 图片是否倾斜 + /// + private bool _isOblique; + + public ImageBrowser() => InitializeComponent(); + + /// + /// 带一个图片路径的构造函数 + /// + /// + public ImageBrowser(string path) : this(new Uri(path)) + { + + } + + /// + /// 带一个图片Uri的构造函数 + /// + /// + public ImageBrowser(Uri uri) : this() + { + try + { + ImageSource = BitmapFrame.Create(uri); + ImgPath = uri.AbsolutePath; + if (File.Exists(ImgPath)) + { + var info = new FileInfo(ImgPath); + ImgSize = info.Length; + } + } + catch + { + PopupWindow.ShowDialog("非法的图片路径!"); + } + } + + private BitmapFrame ImageSource + { + get => (BitmapFrame)GetValue(ImageSourceProperty); + set => SetValue(ImageSourceProperty, value); + } + + private Thickness ImageMargin + { + get => (Thickness)GetValue(ImageMarginProperty); + set => SetValue(ImageMarginProperty, value); + } + + private double ImageWidth + { + get => (double)GetValue(ImageWidthProperty); + set => SetValue(ImageWidthProperty, value); + } + + private double ImageHeight + { + get => (double)GetValue(ImageHeightProperty); + set => SetValue(ImageHeightProperty, value); + } + + public double ImageScale + { + get => (double)GetValue(ImageScaleProperty); + set => SetValue(ImageScaleProperty, value); + } + + private string ScaleStr + { + get => (string)GetValue(ScaleStrProperty); + set => SetValue(ScaleStrProperty, value); + } + + private double ImageRotate + { + get => (double)GetValue(ImageRotateProperty); + set => SetValue(ImageRotateProperty, value); + } + + private bool ShowSmallImg + { + get => (bool)GetValue(ShowSmallImgProperty); + set => SetValue(ShowSmallImgProperty, value); + } + + /// + /// 图片原始宽度 + /// + private double ImageOriWidth { get; set; } + + /// + /// 图片原始高度 + /// + private double ImageOriHeight { get; set; } + + /// + /// 关闭按钮是否显示中 + /// + public bool ShowCloseButton + { + get => _showCloseButton; + set + { + if (_showCloseButton == value) return; + GridTop.BeginAnimation(OpacityProperty, + value ? AnimationHelper.CreateAnimation(1, 100) : AnimationHelper.CreateAnimation(0, 400)); + _showCloseButton = value; + } + } + + /// + /// 底部BorderBottom(包含一些图片操作)是否显示中 + /// + public bool ShowBorderBottom + { + get => _showBorderBottom; + set + { + if (_showBorderBottom == value) return; + BorderBottom.BeginAnimation(OpacityProperty, + value ? AnimationHelper.CreateAnimation(1, 100) : AnimationHelper.CreateAnimation(0, 400)); + _showBorderBottom = value; + } + } + + private static void OnImageScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is ImageBrowser imageBrowser && e.NewValue is double newValue) + { + imageBrowser.ImageWidth = imageBrowser.ImageOriWidth * newValue; + imageBrowser.ImageHeight = imageBrowser.ImageOriHeight * newValue; + imageBrowser.ScaleStr = $"{newValue * 100:#0}%"; + } + } + + /// + /// 初始化 + /// + 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) + { + PopupWindow.ShowDialog("非法的图片尺寸!"); + return; + } + _imgWidHeiScale = width / height; + var scaleWindow = ActualWidth / ActualHeight; + 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; + } + + 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) + { + 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) + { + PopupWindow.ShowDialog(exception.Message); + } + } + + private void ButtonScreenChange_OnClick(object sender, RoutedEventArgs e) => WindowState = IsFullScreen ? WindowState.Maximized : WindowState.Normal; + + private void ButtonClose_OnClick(object sender, RoutedEventArgs e) => Close(); + + private void CanvasBack_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + try + { + DragMove(); + } + catch + { + // ignored + } + } + + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + MoveImg(); + } + + protected override void OnMouseLeave(MouseEventArgs e) + { + base.OnMouseLeave(e); + _imgIsMouseLeftButtonDown = false; + } + + protected override void OnMouseWheel(MouseWheelEventArgs e) + { + base.OnMouseWheel(e); + ScaleImg(e.Delta > 0); + } + + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) + { + base.OnRenderSizeChanged(sizeInfo); + + if (!_isLoaded) return; + + if (ImageWidth < 0.001 || ImageHeight < 0.001) return; + var scaleX = (ImageMargin.Left + ImageWidth * .5) / sizeInfo.PreviousSize.Width; + var scaleY = (ImageMargin.Top + ImageHeight * .5) / sizeInfo.PreviousSize.Height; + + var marginX = scaleX * ActualWidth - ImageWidth * .5; + var marginY = scaleY * ActualHeight - ImageHeight * .5; + + _canMoveX = true; + _canMoveY = true; + if (ImageWidth <= ActualWidth) + { + _canMoveX = false; + marginX = (ActualWidth - ImageWidth) / 2; + } + else if (Math.Abs(ImageMargin.Left) < 0.001) + { + marginX = 0; + } + else + { + var right = Math.Abs(BorderMove.Width - CanvasSmallImg.ActualWidth + BorderMove.Margin.Left); + if (right < 0.001) + { + marginX = ActualWidth - ImageWidth; + } + } + if (ImageHeight <= ActualHeight) + { + _canMoveY = false; + marginY = (ActualHeight - ImageHeight) / 2; + } + else if (Math.Abs(ImageMargin.Top) < 0.001) + { + marginY = 0; + } + else + { + var top = Math.Abs(BorderMove.Height - CanvasSmallImg.ActualHeight + BorderMove.Margin.Top); + if (top < 0.001) + { + marginY = ActualHeight - ImageHeight; + } + } + + ImageMargin = new Thickness(marginX, marginY, 0, 0); + + BorderSmallShowSwitch(); + } + + protected override void OnMouseDoubleClick(MouseButtonEventArgs e) + { + base.OnMouseDoubleClick(e); + + if (e.GetPosition(GridTop).Y > GridTop.ActualHeight) return; + IsFullScreen = !IsFullScreen; + ButtonScreenChange_OnClick(null, null); + } + + private void ImageBrowser_OnLoaded(object sender, RoutedEventArgs e) + { + if (_isLoaded) return; + Init(); + _isLoaded = true; + } + + private void ImageMain_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + if (!(ImageWidth > ActualWidth || ImageHeight > ActualHeight)) + { + DragMove(); + return; + } + _imgMouseDownPoint = Mouse.GetPosition(CanvasMain); + _imgMouseDownMargin = ImageMargin; + _imgIsMouseLeftButtonDown = true; + e.Handled = true; + } + + protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnPreviewMouseLeftButtonUp(e); + _imgIsMouseLeftButtonDown = false; + } + + /// + /// 右下角小图片显示切换 + /// + private void BorderSmallShowSwitch() + { + if (_canMoveX || _canMoveY) + { + if (!_borderSmallIsLoaded) + { + CanvasSmallImg.Background = new VisualBrush(ImageMain); + InitBorderSmall(); + _borderSmallIsLoaded = true; + } + ShowSmallImg = true; + UpdateBorderSmall(); + } + else + { + ShowSmallImg = false; + } + } + + /// + /// 初始化右下角小图片 + /// + 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; + } + } + + /// + /// 更新右下角小图片 + /// + private void UpdateBorderSmall() + { + if (!ShowSmallImg) 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 || Math.Abs(tempScale - 50) < 0.001) + return; + + ImageScale = tempScale; + + var posCanvas = Mouse.GetPosition(CanvasMain); + 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(); + } + + /// + /// 旋转图片 + /// + /// + private void RotateImg(double rotate) + { + _imgActualRotate = rotate; + + _isOblique = ((int)_imgActualRotate - 90) % 180 == 0; + ShowSmallImg = false; + Init(); + InitBorderSmall(); + + var animation = AnimationHelper.CreateAnimation(rotate); + animation.Completed += (s, e1) => { ImageRotate = rotate; }; + animation.FillBehavior = FillBehavior.Stop; + BeginAnimation(ImageRotateProperty, animation); + } + + /// + /// 移动图片 + /// + private void MoveImg() + { + _imgCurrentPoint = Mouse.GetPosition(CanvasMain); + 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(); + } + } + + /// + /// 移动小图片 + /// + 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; + if (marginX < 0) + { + marginX = 0; + } + else if (marginX + BorderMove.Width >= CanvasSmallImg.ActualWidth) + { + marginX = CanvasSmallImg.ActualWidth - BorderMove.Width; + } + + var marginY = _imgSmallMouseDownMargin.Top + subY; + if (marginY < 0) + { + marginY = 0; + } + else if (marginY + BorderMove.Height >= CanvasSmallImg.ActualHeight) + { + marginY = CanvasSmallImg.ActualHeight - 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.ActualWidth * ImageWidth; + } + if (_canMoveY) + { + marginActualY = -marginY / CanvasSmallImg.ActualHeight * 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; + } +} \ No newline at end of file diff --git a/HandyControl/Controls/Window/PopupWindow.xaml b/HandyControl/Controls/Window/PopupWindow.xaml new file mode 100644 index 00000000..0aaca2f7 --- /dev/null +++ b/HandyControl/Controls/Window/PopupWindow.xaml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HandyControl/Controls/Window/PopupWindow.xaml.cs b/HandyControl/Controls/Window/PopupWindow.xaml.cs new file mode 100644 index 00000000..a6e022af --- /dev/null +++ b/HandyControl/Controls/Window/PopupWindow.xaml.cs @@ -0,0 +1,171 @@ +using System; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using HandyControl.Tools; + +// ReSharper disable once CheckNamespace +namespace HandyControl.Controls +{ + /// + /// 弹出窗口 + /// + public partial class PopupWindow + { + private bool IsDialog { get; set; } + + public PopupWindow() + { + Closing += (sender, args) => + { + if (!IsDialog) + Owner?.Focus(); + }; + InitializeComponent(); + try + { + Owner = Application.Current.MainWindow; + } + catch + { + // ignored + } + } + + public PopupWindow(Window owner) : this() + { + Owner = owner; + } + + private void CloseButton_OnClick(object sender, RoutedEventArgs e) + { + Close(); + } + + public UIElement Child + { + get => MainBorder.Child; + set + { + MainBorder.Child = value; + if (value is FrameworkElement temp) + { + TitleBlock.Width = temp.Width - 40; + } + } + } + + public bool ShowTitle + { + set + { + if (!value) + { + TitleGrid.Visibility = Visibility.Collapsed; + Background = Brushes.Transparent; + } + else + { + TitleGrid.Visibility = Visibility.Visible; + Background = new SolidColorBrush(Color.FromRgb(1, 1, 1)); + } + } + } + + public static readonly DependencyProperty ShowCancelProperty = DependencyProperty.Register( + "ShowCancel", typeof(bool), typeof(PopupWindow), new PropertyMetadata(default(bool))); + + + public bool ShowCancel + { + get => (bool)GetValue(ShowCancelProperty); + set => SetValue(ShowCancelProperty, value); + } + + public bool ShowBorder + { + set => MainBorder.BorderThickness = value ? new Thickness(1, 0, 1, 1) : new Thickness(0); + } + + private void TitleBlock_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + DragMove(); + } + + public void Show(FrameworkElement element) + { + var point = ArithmeticHelper.CalSafePoint(element, Child as FrameworkElement); + Left = point.X; + Top = point.Y; + Show(); + } + + public void ShowDialog(FrameworkElement element) + { + var point = ArithmeticHelper.CalSafePoint(element, Child as FrameworkElement); + Left = point.X; + Top = point.Y; + ShowDialog(); + } + + public void Show(Window element, Point point) + { + Left = element.Left + point.X; + Top = element.Top + point.Y; + Show(); + } + + public static void Show(string message) + { + var window = new PopupWindow + { + AllowsTransparency = true, + MyStackPanel = { Visibility = Visibility.Visible }, + MyTextBlock = { Text = message }, + WindowStartupLocation = WindowStartupLocation.CenterScreen, + }; + window.Background = window.FindResource("PrimaryBrush") as SolidColorBrush; + window.Show(); + } + + public static bool? ShowDialog(string message, string title = "提示", bool showCancel = false) + { + var window = new PopupWindow + { + AllowsTransparency = true, + MyStackPanel = { Visibility = Visibility.Visible }, + MyTextBlock = { Text = message }, + IsDialog = true, + WindowStartupLocation = WindowStartupLocation.CenterScreen, + ShowBorder = true, + Title = title, + ShowCancel = showCancel + }; + return window.ShowDialog(); + } + + private void ButtonOk_OnClick(object sender, RoutedEventArgs e) + { + if (IsDialog) + { + DialogResult = true; + } + Close(); + } + + private void ButtonCancle_OnClick(object sender, RoutedEventArgs e) + { + if (IsDialog) + { + DialogResult = false; + } + Close(); + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + Child = null; + } + } +} diff --git a/HandyControl/Controls/Window/WindowBorderless.cs b/HandyControl/Controls/Window/WindowBorderless.cs new file mode 100644 index 00000000..0c2b9484 --- /dev/null +++ b/HandyControl/Controls/Window/WindowBorderless.cs @@ -0,0 +1,254 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; + +// ReSharper disable once CheckNamespace +namespace HandyControl.Controls +{ + /// + /// 无边框窗口 + /// + public class WindowBorderless : Window + { + private Thickness _tempThickness; + + public static readonly DependencyProperty NoUserContentProperty = DependencyProperty.Register( + "NoUserContent", typeof(object), typeof(WindowBorderless), new PropertyMetadata(default(object))); + + public static readonly DependencyProperty CloseButtonHoverBrushProperty = DependencyProperty.Register( + "CloseButtonHoverBrush", typeof(Brush), typeof(WindowBorderless), + new PropertyMetadata(default(Brush))); + + public static readonly DependencyProperty CloseButtonHoverForegroundProperty = + DependencyProperty.Register( + "CloseButtonHoverForeground", typeof(Brush), typeof(WindowBorderless), + new PropertyMetadata(default(Brush))); + + public static readonly DependencyProperty CloseButtonForegroundProperty = DependencyProperty.Register( + "CloseButtonForeground", typeof(Brush), typeof(WindowBorderless), + new PropertyMetadata(Brushes.White)); + + public static readonly DependencyProperty OtherButtonForegroundProperty = DependencyProperty.Register( + "OtherButtonForeground", typeof(Brush), typeof(WindowBorderless), + new PropertyMetadata(Brushes.White)); + + public static readonly DependencyProperty OtherButtonHoverBrushProperty = DependencyProperty.Register( + "OtherButtonHoverBrush", typeof(Brush), typeof(WindowBorderless), + new PropertyMetadata(default(Brush))); + + public static readonly DependencyProperty OtherButtonHoverForegroundProperty = + DependencyProperty.Register( + "OtherButtonHoverForeground", typeof(Brush), typeof(WindowBorderless), + new PropertyMetadata(default(Brush))); + + public static readonly DependencyProperty NoUserAreaBackgroundProperty = DependencyProperty.Register( + "NoUserAreaBackground", typeof(Brush), typeof(WindowBorderless), + new PropertyMetadata(default(Brush))); + + public static readonly DependencyProperty NoUserAreaForegroundProperty = DependencyProperty.Register( + "NoUserAreaForeground", typeof(Brush), typeof(WindowBorderless), + new PropertyMetadata(default(Brush))); + + public static readonly DependencyProperty NoUserAreaHeightProperty = DependencyProperty.Register( + "NoUserAreaHeight", typeof(double), typeof(WindowBorderless), + new PropertyMetadata(28.0)); + + public static readonly DependencyProperty ShowNoUserAreaProperty = DependencyProperty.Register( + "ShowNoUserArea", typeof(bool), typeof(WindowBorderless), new PropertyMetadata(true)); + + public static readonly DependencyProperty ShowTitleProperty = DependencyProperty.Register( + "ShowTitle", typeof(bool), typeof(WindowBorderless), new PropertyMetadata(default(bool))); + + public static readonly DependencyProperty IsFullScreenProperty = DependencyProperty.Register( + "IsFullScreen", typeof(bool), typeof(WindowBorderless), new PropertyMetadata(default(bool), + (o, args) => + { + var ctl = (WindowBorderless)o; + var v = (bool)args.NewValue; + if (v) + { + ctl.OriginState = ctl.WindowState; + ctl.OriginStyle = ctl.WindowStyle; + ctl.OriginResizeMode = ctl.ResizeMode; + ctl.WindowStyle = WindowStyle.None; + //下面三行不能改变,就是故意的 + ctl.WindowState = WindowState.Maximized; + ctl.WindowState = WindowState.Minimized; + ctl.WindowState = WindowState.Maximized; + } + else + { + ctl.WindowState = ctl.OriginState; + ctl.WindowStyle = ctl.OriginStyle; + ctl.ResizeMode = ctl.OriginResizeMode; + } + })); + + public WindowBorderless() + { + Loaded += delegate + { + _tempThickness = BorderThickness; + if (WindowState == WindowState.Maximized) + { + BorderThickness = new Thickness(); + } + + CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, + (s, e) => WindowState = WindowState.Minimized)); + CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, + (s, e) => WindowState = WindowState.Maximized)); + CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, + (s, e) => WindowState = WindowState.Normal)); + CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, (s, e) => Close())); + CommandBindings.Add(new CommandBinding(SystemCommands.ShowSystemMenuCommand, ShowSystemMenu)); + }; + } + + protected override void OnStateChanged(EventArgs e) + { + base.OnStateChanged(e); + if (WindowState == WindowState.Maximized) + { + BorderThickness = new Thickness(); + } + else if (WindowState == WindowState.Normal) + { + BorderThickness = _tempThickness; + } + } + + public Brush CloseButtonForeground + { + get => (Brush)GetValue(CloseButtonForegroundProperty); + set => SetValue(CloseButtonForegroundProperty, value); + } + + public Brush OtherButtonForeground + { + get => (Brush)GetValue(OtherButtonForegroundProperty); + set => SetValue(OtherButtonForegroundProperty, value); + } + + /// + /// 原始状态 + /// + private WindowState OriginState { get; set; } + + /// + /// 原始样式 + /// + private WindowStyle OriginStyle { get; set; } + + /// + /// 原始尺寸调节模式 + /// + private ResizeMode OriginResizeMode { get; set; } + + public double NoUserAreaHeight + { + get => (double)GetValue(NoUserAreaHeightProperty); + set => SetValue(NoUserAreaHeightProperty, value); + } + + public bool IsFullScreen + { + get => (bool)GetValue(IsFullScreenProperty); + set => SetValue(IsFullScreenProperty, value); + } + + public object NoUserContent + { + get => GetValue(NoUserContentProperty); + set => SetValue(NoUserContentProperty, value); + } + + public Brush CloseButtonHoverBrush + { + get => (Brush)GetValue(CloseButtonHoverBrushProperty); + set => SetValue(CloseButtonHoverBrushProperty, value); + } + + public Brush CloseButtonHoverForeground + { + get => (Brush)GetValue(CloseButtonHoverForegroundProperty); + set => SetValue(CloseButtonHoverForegroundProperty, value); + } + + public Brush OtherButtonHoverBrush + { + get => (Brush)GetValue(OtherButtonHoverBrushProperty); + set => SetValue(OtherButtonHoverBrushProperty, value); + } + + public Brush OtherButtonHoverForeground + { + get => (Brush)GetValue(OtherButtonHoverForegroundProperty); + set => SetValue(OtherButtonHoverForegroundProperty, value); + } + + public Brush NoUserAreaBackground + { + get => (Brush)GetValue(NoUserAreaBackgroundProperty); + set => SetValue(NoUserAreaBackgroundProperty, value); + } + + public Brush NoUserAreaForeground + { + get => (Brush)GetValue(NoUserAreaForegroundProperty); + set => SetValue(NoUserAreaForegroundProperty, value); + } + + public bool ShowNoUserArea + { + get => (bool)GetValue(ShowNoUserAreaProperty); + set => SetValue(ShowNoUserAreaProperty, value); + } + + public bool ShowTitle + { + get => (bool)GetValue(ShowTitleProperty); + set => SetValue(ShowTitleProperty, value); + } + + private void ShowSystemMenu(object sender, ExecutedRoutedEventArgs e) + { + var point = WindowState == WindowState.Maximized + ? new Point(0, 28) + : new Point(Left, Top + 28); + SystemCommands.ShowSystemMenu(this, point); + } + + protected override void OnContentRendered(EventArgs e) + { + base.OnContentRendered(e); + if (SizeToContent == SizeToContent.WidthAndHeight) + InvalidateMeasure(); + } + + /// + /// 获取自定义窗口 + /// + /// + public static WindowBorderless GetCustomWindow(FrameworkElement content) + { + var window = new WindowBorderless + { + Style = Application.Current.TryFindResource("CustomWindowStyle") as Style, + Content = content + }; + window.Loaded += (s, e) => + { + window.Width = window.BorderThickness.Left + window.BorderThickness.Right + content.Width; + if (!(window.Template.FindName("GridMenu", window) is Grid nemuArea)) + throw new NullReferenceException("在样式中未找到名称为GridMenu的元素"); + window.Height = window.BorderThickness.Top + window.BorderThickness.Bottom + content.Height + + nemuArea.ActualHeight; + }; + + return window; + } + } +} \ No newline at end of file diff --git a/HandyControl/HandyControl.csproj b/HandyControl/HandyControl.csproj index 392f2094..5c921ce3 100644 --- a/HandyControl/HandyControl.csproj +++ b/HandyControl/HandyControl.csproj @@ -57,6 +57,13 @@ TimeBar.xaml + + ImageBrowser.xaml + + + PopupWindow.xaml + + @@ -140,6 +147,14 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -188,6 +203,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -228,6 +247,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/HandyControl/Properties/AssemblyInfo.cs b/HandyControl/Properties/AssemblyInfo.cs index 700d77f1..32947df1 100644 --- a/HandyControl/Properties/AssemblyInfo.cs +++ b/HandyControl/Properties/AssemblyInfo.cs @@ -10,5 +10,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/HandyControl/Themes/Basic/Geometries.xaml b/HandyControl/Themes/Basic/Geometries.xaml index 621c8d07..381ed8f8 100644 --- a/HandyControl/Themes/Basic/Geometries.xaml +++ b/HandyControl/Themes/Basic/Geometries.xaml @@ -9,6 +9,7 @@ M50.000001,0 L100,51.262779 94.262627,57.141584 50.000001,11.767713 5.7373757,57.151686 0,51.27288 z M498.506684 256.571517 425.359734 256.571517 425.359734 622.190635 720.166063 622.190635 720.166063 549.725206 498.506684 549.725206ZM512.714268 80.162738c-245.740844 0-445.181175 197.577914-445.181175 441.024505s199.439308 441.024505 445.181175 441.024505c245.738797 0 445.178105-197.577914 445.178105-441.024505S758.453065 80.162738 512.714268 80.162738zM512.714268 874.005824c-195.880249 0-356.145349-158.768003-356.145349-352.818581s160.2651-352.821651 356.145349-352.821651c195.877179 0 356.14228 158.77005 356.14228 352.821651S708.591447 874.005824 512.714268 874.005824z M394.24 512L683.52 248.32c10.24-10.24 10.24-25.6 0-35.84-10.24-10.24-25.6-10.24-35.84 0l-307.2 279.04c-5.12 5.12-7.68 12.8-7.68 20.48 0 7.68 2.56 15.36 7.68 20.48l307.2 279.04c10.24 10.24 25.6 10.24 35.84 0 10.24-10.24 10.24-25.6 0-35.84L394.24 512z + M4.1666641,0 C5.2083321,0 6.25,0.41666794 7.0833321,1.25 L57.083331,46.666664 C57.916664,47.499998 58.33333,48.749998 58.333329,49.999998 58.33333,51.249997 57.916664,52.499997 57.083331,53.333331 L7.0833321,98.749996 C5.4166641,100.41666 2.9166641,100.41666 1.2499962,98.749996 -0.41666794,97.083328 -0.41666794,94.583328 1.2499962,92.916664 L48.333331,49.999998 1.2499962,7.0833321 C-0.41666794,5.4166641 -0.41666794,2.9166641 1.2499962,1.25 2.0833282,0.41666794 3.1249962,0 4.1666641,0 z M165.238899 508.178506C164.450369 456.442676 171.767779 404.485842 187.244542 353.863631 266.138632 95.812692 533.436225-51.353028 784.380224 25.368251 1035.324219 102.08953 1174.62994 373.566359 1095.735851 631.617298 1016.84176 889.66824 749.544168 1036.833959 498.600172 960.11268 424.134741 937.346313 357.837833 896.870788 303.973868 842.276436 291.310328 829.441176 291.396506 808.495802 304.166356 795.493625 316.936205 782.491452 337.554042 782.356136 350.217582 795.191397 396.640587 842.243889 453.73137 877.098901 517.975091 896.740177 734.436966 962.919213 965.320335 835.802028 1033.557737 612.607541 1101.795139 389.413057 981.467179 154.919792 765.005305 88.740755 548.543428 22.561718 317.660056 149.678904 249.422655 372.873388 235.597198 418.094418 229.294871 464.461039 230.4403 510.559881L311.240978 429.759202C323.584094 417.416085 343.892513 417.712357 356.601099 430.420946 369.309686 443.129535 369.605959 463.437952 357.262842 475.781068L230.778782 602.265128C229.273826 605.769679 227.098877 609.041396 224.251145 611.889128 211.908029 624.232245 191.59961 623.935974 178.891024 611.227385L40.825428 473.16179C28.11684 460.453206 27.820569 440.144784 40.163685 427.801668 52.506801 415.458551 72.815218 415.754827 85.523806 428.463411L165.238899 508.178506Z M750.3 198.7C598 46.4 351.1 46.4 198.7 198.7s-152.3 399.2 0 551.5C345.1 896.6 578.8 902.3 732 767.3l172.1 172.1 35.4-35.4-172.1-171.9c135-153.2 129.3-387-17.1-533.4z m39.3 403.8c-17.1 42.1-42.2 80-74.7 112.4-32.5 32.5-70.3 57.6-112.4 74.7-40.7 16.5-83.8 24.9-128 24.9s-87.2-8.4-128-24.9c-42.1-17.1-80-42.2-112.4-74.7s-57.6-70.3-74.7-112.4c-16.5-40.7-24.9-83.8-24.9-128s8.4-87.2 24.9-128c17.1-42.1 42.2-80 74.7-112.4s70.3-57.6 112.4-74.7c40.7-16.5 83.8-24.9 128-24.9s87.2 8.4 128 24.9c42.1 17.1 80 42.2 112.4 74.7 32.5 32.5 57.6 70.3 74.7 112.4 16.5 40.7 24.9 83.8 24.9 128s-8.4 87.3-24.9 128zM671 502H496v175h-50V502H271v-50h175V277h50v175h175v50z M750.3 198.7C598 46.4 351.1 46.4 198.7 198.7s-152.3 399.2 0 551.5C345.1 896.6 578.8 902.3 732 767.3l172.1 172.1 35.4-35.4-172.1-171.9c135-153.2 129.3-387-17.1-533.4z m39.3 403.8c-17.1 42.1-42.2 80-74.7 112.4-32.5 32.5-70.3 57.6-112.4 74.7-40.7 16.5-83.8 24.9-128 24.9s-87.2-8.4-128-24.9c-42.1-17.1-80-42.2-112.4-74.7s-57.6-70.3-74.7-112.4c-16.5-40.7-24.9-83.8-24.9-128s8.4-87.2 24.9-128c17.1-42.1 42.2-80 74.7-112.4s70.3-57.6 112.4-74.7c40.7-16.5 83.8-24.9 128-24.9s87.2 8.4 128 24.9c42.1 17.1 80 42.2 112.4 74.7 32.5 32.5 57.6 70.3 74.7 112.4 16.5 40.7 24.9 83.8 24.9 128s-8.4 87.3-24.9 128zM671 502H271v-50h400v50z @@ -19,5 +20,16 @@ M94.186081,59.07 L100,59.07 100,100 59.07,100 59.07,94.186081 94.186081,94.186081 z M4.5814285,58.208999 L41.791,58.208999 41.791,95.418571 35.977005,95.418571 35.977005,68.139304 4.1163101,100 0,95.88369 31.860695,64.022995 4.5814285,64.022995 z M95.88369,0 L100,4.1163101 68.139304,35.977005 95.418571,35.977005 95.418571,41.791 58.208999,41.791 58.208999,4.5814285 64.022995,4.5814285 64.022995,31.860695 z M0,0 L40.929998,0 40.929998,5.8139191 5.8139191,5.8139191 5.8139191,40.929998 0,40.929998 z M716.6003 213.800623c-138.851102-138.915088-364.020238-138.915088-502.935326 0s-138.915088 364.084225 0 502.935326a355.573996 355.573996 0 0 0 502.935326 0 355.573996 355.573996 0 0 0 0-502.935326z m-580.359212 580.359212a465.183184 465.183184 0 1 1 657.783099 0 465.183184 465.183184 0 0 1-657.783099 0z m868.939152 211.156054a63.474789 63.474789 0 0 1-89.837303 0l-89.773316-89.837303a63.410803 63.410803 0 1 1 89.773316-89.773316l89.837303 89.773316a63.346816 63.346816 0 0 1 0 89.837303z M454.464 143.68l-253.44 253.44c-12.032 12.032-12.032 31.36 0 43.392 11.968 11.968 31.36 11.968 43.328 0l237.376-237.376 237.376 237.376c11.968 11.968 31.36 11.968 43.328 0 12.032-12.032 12.032-31.36 0-43.392l-253.44-253.44C491.264 126.016 478.016 124.032 454.464 143.68zM507.968 947.648l252.48-253.376c11.968-11.968 11.968-31.36 0-43.392-11.968-11.968-31.296-11.968-43.264 0l-236.48 237.376L244.16 650.88c-11.968-11.968-31.296-11.968-43.264 0-11.968 12.032-11.968 31.424 0 43.392l252.48 253.376C465.984 960 491.136 964.48 507.968 947.648z + M797.291117 486.21473 224.18848 486.21473c-14.078647 0-25.469068 11.342326-25.469068 25.472138 0 14.028505 11.390421 25.471115 25.469068 25.471115l573.101613 0c14.07967 0 25.470091-11.441587 25.470091-25.471115C822.760185 497.557056 811.370787 486.21473 797.291117 486.21473z + M0.99999996,4.0419998 L0.99999996,12.042 9,12.042 9,4.0419998 z M3.958,1 L3.958,3.0420001 10,3.0420001 10,9 11.958,9 11.958,1 z M2.958,0 L12.958,0 12.958,10 10,10 10,13.042 0,13.042 0,3.0420001 2.958,3.0420001 z + M0.99999994,0.99999994 L0.99999994,9 9,9 9,0.99999994 z M0,0 L10,0 10,10 0,10 z + M938.666667 426.666667h-341.333334V85.333333c0-46.933333-38.4-85.333333-85.333333-85.333333s-85.333333 38.4-85.333333 85.333333v341.333334H85.333333c-46.933333 0-85.333333 38.4-85.333333 85.333333s38.4 85.333333 85.333333 85.333333h341.333334v341.333334c0 46.933333 38.4 85.333333 85.333333 85.333333s85.333333-38.4 85.333333-85.333333v-341.333334h341.333334c46.933333 0 85.333333-38.4 85.333333-85.333333s-38.4-85.333333-85.333333-85.333333z + M62.5797 488.9508c0.2632 42.5185 34.985 77.2116 77.5035 77.5035l743.0216-0.6728c42.5185 0.3215 76.7437-33.9333 76.4518-76.4805l0 0c-0.2918-42.5175-34.985-77.2106-77.5045-77.5035l-743.0216-0.087C96.513 411.4473 62.2879 446.4323 62.5797 488.9508L62.5797 488.9508z + M943.644188 827.215696l-351.176649-608.204749c-42.945473-74.36249-113.147387-74.36249-156.092861 0l-351.176649 608.204749c-42.946498 74.431167-7.811716 135.14955 78.012605 135.14955l702.420949 0C951.455904 962.36422 986.555836 901.645838 943.644188 827.215696zM466.187532 391.579035c12.621133-13.644108 28.66175-20.466675 48.233578-20.466675 19.580028 0 35.612444 6.75389 48.241778 20.194018 12.544256 13.473954 18.820484 30.325365 18.820484 50.587035 0 17.430551-26.19759 145.621205-34.929778 238.882082l-63.105666 0c-7.666162-93.259852-36.090106-221.450507-36.090106-238.882082C447.358847 421.938226 453.643275 405.155491 466.187532 391.579035zM561.76804 835.026386c-13.268949 12.928641-29.062535 19.375023-47.345906 19.375023-18.275171 0-34.076957-6.447407-47.346931-19.375023-13.235123-12.89379-19.818859-28.517221-19.818859-46.869269 0-18.249546 6.583736-34.043131 19.818859-47.278254 13.268949-13.235123 29.07176-19.852685 47.346931-19.852685 18.283371 0 34.076957 6.617562 47.345906 19.852685 13.235123 13.235123 19.827059 29.028709 19.827059 47.278254C581.595099 806.51019 575.003163 822.132597 561.76804 835.026386z + M505.6512 39.0144c-261.2224 3.4816-470.1184 218.112-466.6368 479.4368 3.4816 261.12 218.112 470.1184 479.3344 466.6368 261.2224-3.4816 470.1184-218.112 466.7392-479.3344C981.504 244.4288 766.8736 35.5328 505.6512 39.0144zM558.08 196.608c48.128 0 62.2592 27.9552 62.2592 59.8016 0 39.8336-31.9488 76.6976-86.3232 76.6976-45.568 0-67.1744-22.9376-65.9456-60.8256C468.0704 240.4352 494.7968 196.608 558.08 196.608zM434.7904 807.6288c-32.8704 0-56.9344-19.968-33.8944-107.6224l37.6832-155.5456c6.5536-24.8832 7.68-34.9184 0-34.9184-9.8304 0-52.5312 17.2032-77.7216 34.2016l-16.384-26.9312c79.9744-66.7648 171.8272-105.8816 211.2512-105.8816 32.8704 0 38.2976 38.912 21.9136 98.6112l-43.2128 163.5328c-7.68 28.8768-4.4032 38.912 3.2768 38.912 9.9328 0 42.1888-11.9808 73.9328-36.9664l18.6368 24.8832C552.5504 777.728 467.6608 807.6288 434.7904 807.6288z + M495.469714 0C224.621714 0 0 224.621714 0 495.469714c0 270.884571 224.621714 495.506286 495.469714 495.506286 270.884571 0 495.506286-224.621714 495.506286-495.506286C990.976 224.621714 766.354286 0 495.469714 0z m211.419429 634.221714c19.821714 19.821714 19.821714 46.226286 0 66.048s-46.226286 19.821714-66.048 0l-138.752-138.715428-145.334857 145.334857a51.858286 51.858286 0 0 1-72.667429 0 51.858286 51.858286 0 0 1 0-72.667429l145.334857-145.334857-138.752-138.752c-19.821714-19.821714-19.821714-46.226286 0-66.048s46.262857-19.821714 66.084572 0l138.715428 138.715429 145.371429-145.334857a51.858286 51.858286 0 0 1 72.667428 0 51.858286 51.858286 0 0 1 0 72.667428l-145.371428 145.334857 138.752 138.752z + M512.66048 64.64c-247.424 0-448 200.57728-448 448s200.576 448 448 448 448-200.57728 448-448c0-247.424-200.57728-448-448-448z m250.71232 334.86336L480.98176 681.89312c-15.49568 15.49696-40.61952 15.49696-56.11648 0l-162.9184-162.9184c-15.49568-15.49568-15.49568-40.61824 0-56.1152s40.61952-15.49568 56.11648 0l134.85952 134.85952L707.25504 343.3856c15.49568-15.49568 40.61952-15.49568 56.11648 0s15.49696 40.6208 0.00128 56.11776z + M716.8 375.466667l34.133333 34.133333c17.066667 17.066667 42.666667 17.066667 59.733334 0 17.066667-17.066667 17.066667-42.666667 0-59.733333l-34.133334-34.133334 34.133334-34.133333c17.066667-17.066667 17.066667-42.666667 0-59.733333-17.066667-17.066667-42.666667-17.066667-59.733334 0l-34.133333 34.133333-34.133333-34.133333c-17.066667-17.066667-42.666667-17.066667-59.733334 0-17.066667 17.066667-17.066667 42.666667 0 59.733333l34.133334 34.133333-34.133334 34.133334c-17.066667 17.066667-17.066667 42.666667 0 59.733333 17.066667 17.066667 42.666667 17.066667 59.733334 0l34.133333-34.133333z m-426.666667 0l34.133334 34.133333c17.066667 17.066667 42.666667 17.066667 59.733333 0 17.066667-17.066667 17.066667-42.666667 0-59.733333l-34.133333-34.133334 34.133333-34.133333c17.066667-17.066667 17.066667-42.666667 0-59.733333-17.066667-17.066667-42.666667-17.066667-59.733333 0l-34.133334 34.133333-34.133333-34.133333c-17.066667-17.066667-42.666667-17.066667-59.733333 0-17.066667 17.066667-17.066667 42.666667 0 59.733333l34.133333 34.133333-34.133333 34.133334c-17.066667 17.066667-17.066667 42.666667 0 59.733333 17.066667 17.066667 42.666667 17.066667 59.733333 0l34.133333-34.133333zM0 85.333333c0-51.2 42.666667-85.333333 85.333333-85.333333h853.333334c51.2 0 85.333333 42.666667 85.333333 85.333333v853.333334c0 51.2-42.666667 85.333333-85.333333 85.333333H85.333333c-51.2 0-85.333333-42.666667-85.333333-85.333333V85.333333z m512 469.333334c-136.533333 0-230.4 68.266667-290.133333 196.266666-8.533333 17.066667 0 42.666667 17.066666 59.733334s42.666667 0 59.733334-17.066667c51.2-93.866667 110.933333-145.066667 221.866666-145.066667 102.4 0 170.666667 51.2 221.866667 145.066667 8.533333 17.066667 34.133333 25.6 59.733333 17.066667 17.066667-8.533333 25.6-34.133333 17.066667-59.733334-76.8-128-170.666667-196.266667-307.2-196.266666z + M512 0 30.11843 240.941297l0 542.117406 481.88157 240.941297 481.88157-240.941297L993.88157 240.941297 512 0zM575.776472 768.799969 460.188012 768.799969 460.188012 656.222073l115.588459 0L575.776472 768.799969zM623.335603 509.329685c-52.375829 36.723353-59.600363 55.988096-59.600363 84.885211l0 19.866447L468.616977 614.081343l0-26.489278c0-45.754021 13.846342-80.67124 61.406497-116.791866 46.957428-36.723353 57.79423-62.0082 57.79423-84.282484 0-25.284848-21.67258-54.181962-55.386393-54.181962-42.743457 0-70.436142 26.489278-82.477374 85.486914l-105.956088-21.67258c24.683144-111.976192 82.477374-157.127486 205.289345-157.127486 98.12985 0 157.72919 63.212631 157.72919 131.842639C707.017407 423.240044 688.956071 461.76953 623.335603 509.329685z \ No newline at end of file diff --git a/HandyControl/Themes/Styles/Base/ContextMenuBaseStyle.xaml b/HandyControl/Themes/Styles/Base/ContextMenuBaseStyle.xaml new file mode 100644 index 00000000..465bd8a2 --- /dev/null +++ b/HandyControl/Themes/Styles/Base/ContextMenuBaseStyle.xaml @@ -0,0 +1,218 @@ + + + + + + + + + \ No newline at end of file diff --git a/HandyControl/Themes/Styles/ContextMenu.xaml b/HandyControl/Themes/Styles/ContextMenu.xaml new file mode 100644 index 00000000..419f5a1c --- /dev/null +++ b/HandyControl/Themes/Styles/ContextMenu.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/HandyControl/Tools/ArithmeticHelper.cs b/HandyControl/Tools/ArithmeticHelper.cs index f7856388..e6b09453 100644 --- a/HandyControl/Tools/ArithmeticHelper.cs +++ b/HandyControl/Tools/ArithmeticHelper.cs @@ -7,6 +7,27 @@ namespace HandyControl.Tools { public class ArithmeticHelper { + /// + /// 计算控件在窗口中的可见坐标 + /// + /// + /// + /// + internal static Point CalSafePoint(FrameworkElement element, FrameworkElement showElement) + { + if (element == null || showElement == null) return default(Point); + var point = element.PointToScreen(new Point(0, 0)); + + if (point.X < 0) point.X = 0; + if (point.Y < 0) point.Y = 0; + + var maxLeft = SystemParameters.PrimaryScreenWidth - + (double.IsNaN(showElement.Width) ? showElement.ActualWidth : showElement.Width); + var maxTop = SystemParameters.PrimaryScreenHeight - + (double.IsNaN(showElement.Height) ? showElement.ActualHeight : showElement.Height); + return new Point(maxLeft > point.X ? point.X : maxLeft, maxTop > point.Y ? point.Y : maxTop); + } + /// /// 获取布局范围框 /// diff --git a/HandyControlDemo/HandyControlDemo.csproj b/HandyControlDemo/HandyControlDemo.csproj index e50567a1..27717b2b 100644 --- a/HandyControlDemo/HandyControlDemo.csproj +++ b/HandyControlDemo/HandyControlDemo.csproj @@ -80,5 +80,8 @@ + + + \ No newline at end of file diff --git a/HandyControlDemo/MainWindow.xaml b/HandyControlDemo/MainWindow.xaml index 17ac7585..97c2a5c0 100644 --- a/HandyControlDemo/MainWindow.xaml +++ b/HandyControlDemo/MainWindow.xaml @@ -1,20 +1,46 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + - + - + @@ -876,4 +902,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/HandyControlDemo/MainWindow.xaml.cs b/HandyControlDemo/MainWindow.xaml.cs index e929df74..de19b363 100644 --- a/HandyControlDemo/MainWindow.xaml.cs +++ b/HandyControlDemo/MainWindow.xaml.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.IO; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; +using HandyControl.Controls; using HandyControl.Data; using HandyControl.Tools.Extension; using HandyControlDemo.Data.Model; @@ -299,11 +299,8 @@ namespace HandyControlDemo // StepsExample.Next(); //} - //private void ButtonImageBrowser_OnClick(object sender, RoutedEventArgs e) - //{ - // var window = new ImageBrowser(new Uri("pack://application:,,,/Resources/demo.png")); - // window.Show(); - //} + private void ButtonImageBrowser_OnClick(object sender, RoutedEventArgs e) => + new ImageBrowser(new Uri("pack://application:,,,/Resources/1.jpg")).Show(); private void ColorPicker_OnColorSelected(object sender, FunctionEventArgs e) { diff --git a/HandyControlDemo/Resources/icon-white.png b/HandyControlDemo/Resources/icon-white.png new file mode 100644 index 0000000000000000000000000000000000000000..d0bb47760c2597efdc857303fafce90c2151d651 GIT binary patch literal 16561 zcmeHPJ!lkB5Z;Y{N#KHF7cGL|4@AV^wZa)9Nt6W9G=jgSotj3FG+v=%p%#LTSP5dG zp!idnMg&1Df`y!@AQBrvVj30V`Axi)$KKo9*_rpa-+{?{_ulM$GvAy2z1v(qFgcp* z?e7hOAU8fXau98Sw0kxF-aB>XBbuJmV~3}Mpzj4~cw?|{Ll6uE<0E^f&V^y2FgqK< zC@7c9IW$G+KImp>E6aN%_XIimi^$iW~RF^+}+&gzH*i!#S~je`@JXKpnFaKO|Aa6n)q#?cVK zSs8I)M&e#^T7>|EuWVfn0URV372p*|Ljb2VIl-sdc*XHefQt&?5Fp0U5RkTVG%pT} z2T8m#hI0-9Vw{x*P}VLdu-|Z+_}qXA$iZQ{sy6dV z0PfW2nc>=MSmz_+3h=!PIL|b}VO_lKqC=QT>%^O&nKea0x)UQkimp# zY%>i3ja>~)-a7;^iL#kBQU%!JV~u&eCcvXD`bEYuRwT(rMO<6_N}gVxsXid4Y!FRr z2#9>tYByn0^(6+jzXbJ0fbU~~cx4P$IlGz|$2S2+9^!6O6Chq0FF|HwCJMQ*;iW+m=sR>{lN--AWXb7N~c0nH_KzaksCN%Ft?f_%b<_P2TP=|h1E)zI#As^u6 z2=xC-pg#zmhq{s_IJyNLh%!aL3wjMI7T50&Eh4zL&>rXxsJ6o3qDp9grxzqYLkVL& zR4lFu5C>AP4SlRoy>b!Zb_f7%^j>YdN{K2!_4Y-RGxwAZf^-gV-xsOzwG*AX=#ut2 vl-?