WPF 自定义放大镜控件
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF 自定义放大镜控件相关的知识,希望对你有一定的参考价值。
控件名:Magnifier
作 者:WPFDevelopersOrg - 驚鏵
原文链接[1]:https://github.com/WPFDevelopersOrg/WPFDevelopers
框架使用
.NET40
;Visual Studio 2019
;实现此功能需要用到
VisualBrush
,放大镜展现使用Canvas
->Ellipse
.可以使用
VisualBrush
创建放大效果。设置
Visual
获取或设置画笔的内容。设置
ViewboxUnits
Absolute
坐标系与边界框无关。设置
Viewbox
获取或设置TileBrush
图块中内容的位置和尺寸。
当鼠标移动获取当前坐标点修改
VisualBrush
的Viewbox
。鼠标移动修改
Ellipse
的Canvas.Left
与Canvas.Top
跟随鼠标。接着上一篇把放大镜做成控件方便使用。
新建
Magnifier
获取父控件,为父控件创建装饰器把Magnifier
添加到装饰器Child
。需注意当鼠标移动获取在父控件上获取
Visual
的偏移量VisualTreeHelper.GetOffset
。
1) Magnifier.xaml
代码如下:
<Style TargetType="x:Type controls:Magnifier" BasedOn="StaticResource ControlBasicStyle">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="IsHitTestVisible" Value="False" />
<Setter Property="Width" Value="200"/>
<Setter Property="Height" Value="200"/>
<Setter Property="BorderThickness" Value="8"/>
<Setter Property="BorderBrush" Value="DynamicResource PrimaryNormalSolidColorBrush"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="x:Type controls:Magnifier">
<Canvas Name="PART_Canvas">
<Border
x:Name="PART_Border"
BorderBrush="TemplateBinding BorderBrush"
BorderThickness="TemplateBinding BorderThickness"
Background="TemplateBinding Background"
Height="TemplateBinding Height"
Width="TemplateBinding Height"
CornerRadius="TemplateBinding CornerRadius">
<Ellipse>
<Ellipse.Fill>
<VisualBrush
x:Name="PART_VisualBrush"
Visual="Binding ParentTarget,RelativeSource=RelativeSource TemplatedParent"
ViewboxUnits="Absolute" />
</Ellipse.Fill>
</Ellipse>
</Border>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
2) Magnifier.xaml.cs
代码如下:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using WPFDevelopers.Utilities;
namespace WPFDevelopers.Controls
[TemplatePart(Name = BorderTemplateName, Type = typeof(Border))]
[TemplatePart(Name = VisualBrushTemplateName, Type = typeof(VisualBrush))]
public class Magnifier : Control
private const string BorderTemplateName = "PART_Border";
private const string VisualBrushTemplateName = "PART_VisualBrush";
public static Magnifier Default = new Magnifier();
public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(Magnifier), new PropertyMetadata(new CornerRadius(0)));
public static readonly DependencyProperty ParentTargetProperty =
DependencyProperty.Register("ParentTarget", typeof(FrameworkElement), typeof(Magnifier),
new PropertyMetadata(default, OnParentTargetChanged));
public static readonly DependencyProperty AddProperty =
DependencyProperty.RegisterAttached("Add", typeof(Magnifier), typeof(Magnifier),
new PropertyMetadata(default, OnAddChanged));
private AdornerContainer _adornerContainer;
private Border _border;
private double _factor = 0.5;
private VisualBrush _visualBrush = new VisualBrush();
public CornerRadius CornerRadius
get => (CornerRadius)GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
public FrameworkElement ParentTarget
get => (FrameworkElement)GetValue(ParentTargetProperty);
set => SetValue(ParentTargetProperty, value);
private static void OnParentTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
var magnifier = (Magnifier)d;
magnifier.OnParentTargetChanged((FrameworkElement)e.NewValue);
private void OnParentTargetChanged(FrameworkElement element)
if (element == null) return;
element.Unloaded -= Element_Unloaded;
element.Unloaded += Element_Unloaded;
element.MouseEnter -= Element_MouseEnter;
element.MouseEnter += Element_MouseEnter;
element.MouseLeave -= Element_MouseLeave;
element.MouseLeave += Element_MouseLeave;
element.MouseMove -= Element_MouseMove;
element.MouseMove += Element_MouseMove;
element.MouseWheel -= Element_MouseWheel;
element.MouseWheel += Element_MouseWheel;
private void Element_MouseWheel(object sender, MouseWheelEventArgs e)
if (e.Delta > 0)
_factor -= 0.2;
else
_factor += 0.2;
_factor = _factor < 0.2 ? 0.2 : _factor;
_factor = _factor > 1 * 4 ? 4 : _factor;
MoveMagnifier();
private void Element_MouseLeave(object sender, MouseEventArgs e)
if (_adornerContainer == null) return;
var layer = AdornerLayer.GetAdornerLayer(ParentTarget);
if (layer != null) layer.Remove(_adornerContainer);
if (_adornerContainer != null)
_adornerContainer.Child = null;
_adornerContainer = null;
private void Element_Unloaded(object sender, RoutedEventArgs e)
if (sender is FrameworkElement element)
element.Unloaded -= Element_Unloaded;
private void Element_MouseMove(object sender, MouseEventArgs e)
MoveMagnifier();
private void MoveMagnifier()
if (_border == null) return;
var length = Width * _factor;
var radius = length / 2;
var parentTargetPoint = Mouse.GetPosition(ParentTarget);
var parentTargetVector = VisualTreeHelper.GetOffset(ParentTarget);
var size = new Size(length, length);
var viewboxRect =
new Rect(
new Point(parentTargetPoint.X - radius + parentTargetVector.X,
parentTargetPoint.Y - radius + parentTargetVector.Y), size);
_visualBrush.Viewbox = viewboxRect;
var adornerPoint = Mouse.GetPosition(_adornerContainer);
_border.SetValue(Canvas.LeftProperty, adornerPoint.X - Width / 2);
_border.SetValue(Canvas.TopProperty, adornerPoint.Y - Height / 2);
private void Element_MouseEnter(object sender, MouseEventArgs e)
ParentTarget.Cursor = Cursors.Cross;
if (_adornerContainer == null)
var layer = AdornerLayer.GetAdornerLayer(ParentTarget);
if (layer == null) return;
_adornerContainer = new AdornerContainer(layer)
Child = this
;
layer.Add(_adornerContainer);
public static Magnifier GetAdd(DependencyObject obj)
return (Magnifier)obj.GetValue(AddProperty);
public static void SetAdd(DependencyObject obj, int value)
obj.SetValue(AddProperty, value);
private static void OnAddChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
if (d is FrameworkElement parent)
var element = (Magnifier)e.NewValue;
element.OnAddChanged(parent);
private void OnAddChanged(FrameworkElement parent)
ParentTarget = parent;
public override void OnApplyTemplate()
base.OnApplyTemplate();
CornerRadius = new CornerRadius(Width / 2);
_border = GetTemplateChild(BorderTemplateName) as Border;
_visualBrush = GetTemplateChild(VisualBrushTemplateName) as VisualBrush ?? new VisualBrush();
1) MagnifierExample.xaml
代码如下:
<Image Source="/Images/Craouse/0.jpg" Stretch="None"
wpfdev:Magnifier.Add="x:Static wpfdev:Magnifier.Default"/>
参考资料
[1]
原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers
以上是关于WPF 自定义放大镜控件的主要内容,如果未能解决你的问题,请参考以下文章