控件名: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"><Borderx: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