Magnifier.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using System.Windows;
  2. using System.Windows.Documents;
  3. using System.Windows.Input;
  4. using System.Windows.Media;
  5. using HandyControl.Data;
  6. using HandyControl.Interactivity;
  7. using HandyControl.Tools;
  8. using HandyControl.Tools.Extension;
  9. namespace HandyControl.Controls;
  10. [TemplatePart(Name = ElementVisualBrush, Type = typeof(VisualBrush))]
  11. public class Magnifier : AdornerElement
  12. {
  13. private AdornerContainer _adornerContainer;
  14. private Size _viewboxSize;
  15. private const string ElementVisualBrush = "PART_VisualBrush";
  16. private VisualBrush _visualBrush = new();
  17. private readonly TranslateTransform _translateTransform;
  18. public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register(
  19. nameof(HorizontalOffset), typeof(double), typeof(Magnifier), new PropertyMetadata(ValueBoxes.Double0Box));
  20. public double HorizontalOffset
  21. {
  22. get => (double) GetValue(HorizontalOffsetProperty);
  23. set => SetValue(HorizontalOffsetProperty, value);
  24. }
  25. public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register(
  26. nameof(VerticalOffset), typeof(double), typeof(Magnifier), new PropertyMetadata(ValueBoxes.Double0Box));
  27. public double VerticalOffset
  28. {
  29. get => (double) GetValue(VerticalOffsetProperty);
  30. set => SetValue(VerticalOffsetProperty, value);
  31. }
  32. public static Magnifier Default => new();
  33. public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register(
  34. nameof(Scale), typeof(double), typeof(Magnifier), new PropertyMetadata(5.0, OnScaleChanged), ValidateHelper.IsInRangeOfPosDouble);
  35. private static void OnScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((Magnifier) d).UpdateViewboxSize();
  36. public double Scale
  37. {
  38. get => (double) GetValue(ScaleProperty);
  39. set => SetValue(ScaleProperty, value);
  40. }
  41. public Magnifier()
  42. {
  43. _translateTransform = new TranslateTransform();
  44. RenderTransform = _translateTransform;
  45. }
  46. public override void OnApplyTemplate()
  47. {
  48. base.OnApplyTemplate();
  49. var visualBrush = GetTemplateChild(ElementVisualBrush) as VisualBrush ?? new VisualBrush();
  50. visualBrush.Viewbox = _visualBrush.Viewbox;
  51. _visualBrush = visualBrush;
  52. }
  53. protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
  54. {
  55. base.OnRenderSizeChanged(sizeInfo);
  56. UpdateViewboxSize();
  57. }
  58. private void UpdateViewboxSize() => _viewboxSize = new Size(ActualWidth / Scale, ActualHeight / Scale);
  59. protected sealed override void OnTargetChanged(FrameworkElement element, bool isNew)
  60. {
  61. base.OnTargetChanged(element, isNew);
  62. if (element == null) return;
  63. if (!isNew)
  64. {
  65. element.MouseEnter -= Element_MouseEnter;
  66. element.MouseLeave -= Element_MouseLeave;
  67. element.MouseMove -= Element_MouseMove;
  68. ElementTarget = null;
  69. }
  70. else
  71. {
  72. element.MouseEnter += Element_MouseEnter;
  73. element.MouseLeave += Element_MouseLeave;
  74. element.MouseMove += Element_MouseMove;
  75. ElementTarget = element;
  76. }
  77. }
  78. protected override void Dispose() => HideAdornerElement();
  79. private void UpdateLocation()
  80. {
  81. var targetPoint = Mouse.GetPosition(Target);
  82. var subX = targetPoint.X - _visualBrush.Viewbox.Width / 2;
  83. var subY = targetPoint.Y - _visualBrush.Viewbox.Height / 2;
  84. var targetVector = VisualTreeHelper.GetOffset(Target);
  85. _visualBrush.Viewbox = new Rect(new Point(subX + targetVector.X, subY + targetVector.Y), _viewboxSize);
  86. var adornerPoint = Mouse.GetPosition(_adornerContainer);
  87. _translateTransform.X = adornerPoint.X + HorizontalOffset;
  88. _translateTransform.Y = adornerPoint.Y + VerticalOffset;
  89. }
  90. private void Element_MouseMove(object sender, MouseEventArgs e) => UpdateLocation();
  91. private void Element_MouseLeave(object sender, MouseEventArgs e) => HideAdornerElement();
  92. private void Element_MouseEnter(object sender, MouseEventArgs e) => ShowAdornerElement();
  93. private void HideAdornerElement()
  94. {
  95. if (_adornerContainer == null) return;
  96. var layer = AdornerLayer.GetAdornerLayer(Target);
  97. if (layer != null)
  98. {
  99. layer.Remove(_adornerContainer);
  100. }
  101. else if (_adornerContainer is { Parent: AdornerLayer parent })
  102. {
  103. parent.Remove(_adornerContainer);
  104. }
  105. if (_adornerContainer != null)
  106. {
  107. _adornerContainer.Child = null;
  108. _adornerContainer = null;
  109. }
  110. }
  111. private void ShowAdornerElement()
  112. {
  113. if (_adornerContainer == null)
  114. {
  115. var layer = AdornerLayer.GetAdornerLayer(Target);
  116. if (layer == null) return;
  117. _adornerContainer = new AdornerContainer(layer)
  118. {
  119. Child = this
  120. };
  121. layer.Add(_adornerContainer);
  122. }
  123. this.Show();
  124. }
  125. }