diff --git a/src/Shared/HandyControlDemo_Shared/Data/MessageToken.cs b/src/Shared/HandyControlDemo_Shared/Data/MessageToken.cs index 21daf25a..81f4aaab 100644 --- a/src/Shared/HandyControlDemo_Shared/Data/MessageToken.cs +++ b/src/Shared/HandyControlDemo_Shared/Data/MessageToken.cs @@ -102,6 +102,8 @@ public static readonly string CardDemoCtl = nameof(CardDemoCtl); + public static readonly string MagnifierDemoCtl = nameof(MagnifierDemoCtl); + public static readonly string ButtonDemoCtl = nameof(ButtonDemoCtl); public static readonly string RepeatButtonDemoCtl = nameof(RepeatButtonDemoCtl); diff --git a/src/Shared/HandyControlDemo_Shared/Data/MessageToken.tt b/src/Shared/HandyControlDemo_Shared/Data/MessageToken.tt index 5c2eff75..9dd5242f 100644 --- a/src/Shared/HandyControlDemo_Shared/Data/MessageToken.tt +++ b/src/Shared/HandyControlDemo_Shared/Data/MessageToken.tt @@ -53,7 +53,8 @@ var controlList = new List "GridDemoCtl", "RangeSliderDemoCtl", "ButtonGroupDemoCtl", - "CardDemoCtl" + "CardDemoCtl", + "MagnifierDemoCtl" }; var styleList = new List { diff --git a/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems b/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems index 0e7f7718..29c71932 100644 --- a/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems +++ b/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems @@ -54,6 +54,9 @@ CardDemoCtl.xaml + + MagnifierDemoCtl.xaml + RangeSliderDemoCtl.xaml @@ -420,6 +423,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.Designer.cs b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.Designer.cs index 1ef33d47..510ba758 100644 --- a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.Designer.cs +++ b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.Designer.cs @@ -771,6 +771,15 @@ namespace HandyControlDemo.Properties.Langs { } } + /// + /// 查找类似 放大镜 的本地化字符串。 + /// + public static string Magnifier { + get { + return ResourceManager.GetString("Magnifier", resourceCulture); + } + } + /// /// 查找类似 菜单 的本地化字符串。 /// diff --git a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.en.resx b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.en.resx index 4298ede4..fcdb3a41 100644 --- a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.en.resx +++ b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.en.resx @@ -627,4 +627,7 @@ TextDialog with timer + + Magnifier + \ No newline at end of file diff --git a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.resx b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.resx index e5cabbbb..9b30e734 100644 --- a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.resx +++ b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.resx @@ -627,4 +627,7 @@ 文本对话框,带计时器 + + 放大镜 + \ No newline at end of file diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/MagnifierDemoCtl.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/MagnifierDemoCtl.xaml new file mode 100644 index 00000000..ca5b7eed --- /dev/null +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/MagnifierDemoCtl.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/MagnifierDemoCtl.xaml.cs b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/MagnifierDemoCtl.xaml.cs new file mode 100644 index 00000000..a09d3502 --- /dev/null +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/MagnifierDemoCtl.xaml.cs @@ -0,0 +1,10 @@ +namespace HandyControlDemo.UserControl +{ + public partial class MagnifierDemoCtl + { + public MagnifierDemoCtl() + { + InitializeComponent(); + } + } +} diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml index d137f77e..f4d14f70 100644 --- a/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml @@ -195,6 +195,11 @@ + + + + + @@ -415,7 +420,7 @@ - + diff --git a/src/Shared/HandyControl_Shared/Controls/Other/Magnifier.cs b/src/Shared/HandyControl_Shared/Controls/Other/Magnifier.cs new file mode 100644 index 00000000..d553789d --- /dev/null +++ b/src/Shared/HandyControl_Shared/Controls/Other/Magnifier.cs @@ -0,0 +1,142 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using HandyControl.Interactivity; +using HandyControl.Tools.Extension; + +namespace HandyControl.Controls +{ + [TemplatePart(Name = ElementVisualBrush, Type = typeof(VisualBrush))] + public class Magnifier : Control + { + private Size _viewboxSize; + + private Adorner _adorner; + + private UIElement _elementTarget; + + private const string ElementVisualBrush = "PART_VisualBrush"; + + private VisualBrush _visualBrush = new VisualBrush(); + + public static readonly DependencyProperty InstanceProperty = DependencyProperty.RegisterAttached( + "Instance", typeof(Magnifier), typeof(Magnifier), new PropertyMetadata(default(Magnifier), OnMagnifierChanged)); + + private static void OnMagnifierChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (!(d is UIElement target)) return; + var magnifier = (Magnifier)e.NewValue; + magnifier.Target = target; + } + + public static void SetInstance(DependencyObject element, Magnifier value) + => element.SetValue(InstanceProperty, value); + + public static Magnifier GetInstance(DependencyObject element) + => (Magnifier) element.GetValue(InstanceProperty); + + internal static readonly DependencyProperty TargetProperty = DependencyProperty.Register( + "Target", typeof(UIElement), typeof(Magnifier), new PropertyMetadata(default(UIElement), OnTargetChanged)); + + private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var ctl = (Magnifier) d; + ctl.UpdateTarget(ctl._elementTarget, false); + ctl.UpdateTarget((UIElement)e.NewValue, true); + } + + internal UIElement Target + { + get => (UIElement)GetValue(TargetProperty); + set => SetValue(TargetProperty, value); + } + + public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register( + "Scale", typeof(double), typeof(Magnifier), new PropertyMetadata(5.0, OnScaleChanged)); + + private static void OnScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((Magnifier)d).UpdateViewboxSize(); + + public double Scale + { + get => (double)GetValue(ScaleProperty); + set => SetValue(ScaleProperty, value); + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + var visualBrush = GetTemplateChild(ElementVisualBrush) as VisualBrush ?? new VisualBrush(); + visualBrush.Viewbox = _visualBrush.Viewbox; + _visualBrush = visualBrush; + } + + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) + { + base.OnRenderSizeChanged(sizeInfo); + UpdateViewboxSize(); + } + + private void UpdateViewboxSize() => _viewboxSize = new Size(ActualWidth / Scale, ActualHeight / Scale); + + private void UpdateTarget(UIElement element , bool isNew) + { + if (element == null) return; + + if (!isNew) + { + element.MouseEnter -= Element_MouseEnter; + element.MouseLeave -= Element_MouseLeave; + element.MouseMove -= Element_MouseMove; + _elementTarget = null; + } + else + { + element.MouseEnter += Element_MouseEnter; + element.MouseLeave += Element_MouseLeave; + element.MouseMove += Element_MouseMove; + _elementTarget = element; + } + } + + private void UpdateLocation(Point adornerPoint) + { + var targetPoint = Mouse.GetPosition(Target); + + var subX = targetPoint.X - _visualBrush.Viewbox.Width / 2; + var subY = targetPoint.Y - _visualBrush.Viewbox.Height / 2; + + _visualBrush.Viewbox = new Rect(new Point(subX, subY), _viewboxSize); + + var x = adornerPoint.X - ActualWidth / 2; + var y = adornerPoint.Y - ActualHeight / 2; + Arrange(new Rect(x, y, ActualWidth, ActualHeight)); + + Console.WriteLine(new Rect(x, y, ActualWidth, ActualHeight)); + } + + private void Element_MouseMove(object sender, MouseEventArgs e) => UpdateLocation(Mouse.GetPosition(_adorner)); + + private void Element_MouseLeave(object sender, MouseEventArgs e) => _adorner?.Collapse(); + + private void Element_MouseEnter(object sender, MouseEventArgs e) + { + if (_adorner == null) + { + var layer = AdornerLayer.GetAdornerLayer(Target); + if (layer == null) return; + _adorner = new AdornerContainer(layer) + { + Child = this + }; + layer.Add(_adorner); + } + + _adorner.Show(); + UpdateLocation(Mouse.GetPosition(_adorner)); + } + } +} diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems index 2bbc21ab..a13d94bc 100644 --- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems +++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems @@ -19,6 +19,7 @@ + @@ -354,6 +355,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -646,6 +651,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/MagnifierBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/MagnifierBaseStyle.xaml new file mode 100644 index 00000000..ebc512c3 --- /dev/null +++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/MagnifierBaseStyle.xaml @@ -0,0 +1,31 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Magnifier.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Magnifier.xaml new file mode 100644 index 00000000..4fa2946b --- /dev/null +++ b/src/Shared/HandyControl_Shared/Themes/Styles/Magnifier.xaml @@ -0,0 +1,10 @@ + + + + + + +