WPF 中的放大效果






4.38/5 (17投票s)
在 WPF 中创建放大效果以及如何使用我的放大镜控件
引言
本文的目的是让您了解如何在 WPF 应用程序中创建放大效果。希望您能从中掌握一些概念,这些概念将有助于您开发需要此类功能的完整应用程序。我还将解释如何使用我的 Magnifier
控件,这是一个 UserControl
,其功能类似于具有放大区域的 Image
控件。
要求
要运行从上面的下载链接提供的项目,你需要以下之一
- Visual Studio 2010
- Expression Blend
如果您拥有 Visual Studio 2008,可以从 此处 下载源文件。
注意:如果您使用的是 Visual Studio 的 Express 版本,请确保使用 Visual Basic Express 打开解决方案。
Magnifier (演示)
工作原理
将鼠标指针移到图像上。将显示一个放大区域。移动鼠标可在图像周围移动放大区域。(如果您开始感到担忧,我敦促您不要担心。您应该看到别人的车。)
设计和布局
我将所有内容都放在 Expression Blend 中。下图显示了元素在“对象和时间轴”面板中的布局。
这里感兴趣的元素是 MainGrid
和 ClipGrid
,它们都是默认 LayoutRoot
的子元素。ClipGrid
实际上是 MainGrid
的一个副本,我只是在复制粘贴后重命名了它。两个 Grid
控件都有 Image
控件,这些控件具有相同的图像。
注意: ClipImage
的 Cursor
属性设置为“无”。
代码
我们有三个全局变量
Private ClipRctGeo As New RectangleGeometry()
Private ClipPath As New Path()
Private ScaleTr As New ScaleTransform()
在 MainWindow
的 Initialized
事件处理程序中,我们设置了这些对象的属性。
Private Sub MainWindow_Initialized(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Initialized
' Set the position and dimensions of
' the clipping rectangle that defines
' the magnification region.
ClipRctGeo.Rect = New Rect(0, 0, 80, 80)
ClipPath.Stroke = Brushes.Gainsboro
ClipPath.StrokeThickness = 2
ClipPath.Data = ClipRctGeo
ClipGrid.Children.Add(ClipPath)
ClipGrid.Clip = ClipRctGeo
' Set magnification to 150%.
ScaleTr.ScaleX = 1.5
ScaleTr.ScaleY = 1.5
ClipGrid.RenderTransform = ScaleTr
ClipGrid.Visibility = Windows.Visibility.Hidden
End Sub
ClipPath
定义了 RectangleGeometry
、ClipRctGeo
的边框/描边颜色。老实说,我不知道 gainsboro 是什么,但它在浅色和深色背景上都效果很好。请注意,我们正在裁剪 Grid
控件 ClipGrid
。
当 MainGrid
的 MouseEnter
事件触发时,我们执行以下操作(请记住,在 MainWindow
的 Initialized
事件期间,ClipGrid
已被裁剪,并且其 Visibility
属性设置为“隐藏”,而 ClipGrid
在 LayoutRoot
中堆叠在 MainGrid
之上)。
Private Sub MainGrid_MouseEnter(ByVal sender As Object, _
ByVal e As System.Windows.Input.MouseEventArgs) _
Handles MainGrid.MouseEnter
' Set magnifying location.
MoveMagnifier(e)
If ClipGrid.Visibility = Windows.Visibility.Hidden Then
ClipGrid.Visibility = Windows.Visibility.Visible
End If
End Sub
MoveMagnifier
方法执行以下操作:
Private Sub MoveMagnifier(ByVal e As System.Windows.Input.MouseEventArgs)
Dim mouseX As Double = e.GetPosition(ClipGrid).X
Dim mouseY As Double = e.GetPosition(ClipGrid).Y
ScaleTr.CenterX = mouseX
ScaleTr.CenterY = mouseY
' Set the location and dimensions of the
' clipping rectangle.
ClipRctGeo.Rect = New Rect((mouseX - 40), (mouseY - 40), 80, 80)
End Sub
在上面的方法中,我们设置了 ScaleTransform
对象 的中心点,以便“放大”从鼠标指针的位置发生,而鼠标指针是不可见的,因为我们将 ClipImage
的 Cursor
属性设置为 None
。我敢肯定,您现在已经明白,通过缩放 ClipGrid
,我们可以制造出图像被放大的错觉。
当调用 ClipGrid
的 MouseMove
事件处理程序时,放大区域会移动。
Private Sub ClipGrid_MouseMove(ByVal sender As Object, _
ByVal e As System.Windows.Input.MouseEventArgs) _
Handles ClipGrid.MouseMove
' Move magnifying region.
MoveMagnifier(e)
End Sub
当鼠标指针移出可放大区域时,会发生以下情况:
Private Sub ClipGrid_MouseLeave(ByVal sender As Object, _
ByVal e As System.Windows.Input.MouseEventArgs) _
Handles ClipGrid.MouseLeave
' Hide the canvas when the pointer is beyond
' the region of interest.
ClipGrid.Visibility = Windows.Visibility.Hidden
End Sub
图像并非全部
由于我们实际上在“放大”一个布局容器(在本例中为 Grid
控件),这意味着我们不仅限于创建图像的放大效果。下图显示了 RichTextBox
控件的视在放大效果。
您可以从 此处 下载与上一个屏幕截图相关的演示。
Magnifier 控件
正如我在引言部分所解释的,Magnifier
控件的功能类似于具有放大区域的 Image
控件。要使用 Magnifier
控件,请添加对 Magnifier.dll 的引用,该文件可从上面的下载链接获取。该 DLL 应在项目“引用”文件夹中列出。
激活“资产”面板,然后在搜索文本框中输入“magnifier”一词。键入前几个字母时,您应该会看到 Magnifier
控件显示出来。
双击 Magnifier
控件将其添加到您的布局容器,或选择它并直接拖出。在“属性”面板的“Miscellaneous”部分,查找 ImagesSource
属性,然后单击省略号按钮,从您想要放置图像的位置选择一个图像。
代码
Magnifier
控件的代码与我之前解释的代码类似,只是增加了一个 DependencyProperty
。
Class Magnifier
Private ClipRctGeo As New RectangleGeometry()
Private ClipPath As New Path()
Private ScaleTr As New ScaleTransform()
Public Sub New()
MyBase.New()
Me.InitializeComponent()
' Insert code required on object creation below this point.
End Sub
Private Sub MagnifierControl_Initialized(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Initialized
ClipRctGeo.Rect = New Rect(0, 0, 80, 80)
ClipPath.Stroke = Brushes.Gainsboro
ClipPath.StrokeThickness = 2
ClipPath.Data = ClipRctGeo
ClipGrid.Children.Add(ClipPath)
ClipGrid.Clip = ClipRctGeo
' Set magnification to 150%.
ScaleTr.ScaleX = 1.5
ScaleTr.ScaleY = 1.5
ClipGrid.RenderTransform = ScaleTr
ClipGrid.Visibility = Windows.Visibility.Hidden
End Sub
Private Sub MoveMagnifier(ByVal e As System.Windows.Input.MouseEventArgs)
Dim mouseX As Double = e.GetPosition(ClipGrid).X
Dim mouseY As Double = e.GetPosition(ClipGrid).Y
ScaleTr.CenterX = mouseX
ScaleTr.CenterY = mouseY
' Set the location and dimensions of the
' clipping rectangle.
ClipRctGeo.Rect = New Rect((mouseX - 40), (mouseY - 40), 80, 80)
End Sub
Private Sub ClipGrid_MouseLeave(ByVal sender As Object, _
ByVal e As System.Windows.Input.MouseEventArgs) _
Handles ClipGrid.MouseLeave
' Hide the canvas when the pointer is beyond
' the region of interest.
ClipGrid.Visibility = Windows.Visibility.Hidden
End Sub
Private Sub ClipGrid_MouseMove(ByVal sender As Object, _
ByVal e As System.Windows.Input.MouseEventArgs) _
Handles ClipGrid.MouseMove
' Move magnifying region.
MoveMagnifier(e)
End Sub
Private Sub MainGrid_MouseEnter(ByVal sender As Object, _
ByVal e As System.Windows.Input.MouseEventArgs) _
Handles MainGrid.MouseEnter
' Set magnifying location.
MoveMagnifier(e)
If ClipGrid.Visibility = Windows.Visibility.Hidden Then
ClipGrid.Visibility = Windows.Visibility.Visible
End If
End Sub
Public Property ImagesSource() As ImageSource
Get
Return CType(GetValue(ImagesSourceProperty), ImageSource)
End Get
Set(ByVal value As ImageSource)
SetValue(ImagesSourceProperty, value)
End Set
End Property
Public Shared ImagesSourceProperty As DependencyProperty = _
DependencyProperty.Register("ImagesSource", _
GetType(ImageSource), _
GetType(Magnifier), _
New FrameworkPropertyMetadata( _
New PropertyChangedCallback_
(AddressOf ChangeSource)))
Private Shared Sub ChangeSource(ByVal source As DependencyObject, _
ByVal e As DependencyPropertyChangedEventArgs)
CType(source, Magnifier).MainImage.Source = CType(e.NewValue, ImageSource)
CType(source, Magnifier).ClipImage.Source = CType(e.NewValue, ImageSource)
End Sub
End Class
Magnifier 控件 v2.0
Magnifier
控件的 2.0 版本允许用户放大放大区域。向上滚动鼠标滚轮将放大放大的区域,反之亦然。
这是使此成为可能 的代码。
Private Sub ClipGrid_MouseWheel(ByVal sender As Object, _
ByVal e As System.Windows.Input.MouseWheelEventArgs) _
Handles ClipGrid.MouseWheel
' Zoom in when the user scrolls up
' and vice-versa.
If e.Delta > 0 Then
' Zoom-in.
If zoom < 2.5 Then
zoom += 0.5
ScaleTr.ScaleX = zoom
ScaleTr.ScaleY = zoom
MoveMagnifier(e)
End If
Else
' Zoom-out.
If zoom > 1.5 Then
zoom -= 0.5
ScaleTr.ScaleX = zoom
ScaleTr.ScaleY = zoom
MoveMagnifier(e)
End If
End If
End Sub
其他选项
您还可以采取其他选项来在 WPF 中创建放大效果,因此您可以选择最适合您的方法。感谢 Sacha Barber 让我了解到这些。
结论
感谢您花时间阅读本文。我希望它很有用,并且您从中学习到了将来可能在应用程序中遇到的内容。祝您一切顺利!
历史
- 2011 年 3 月 8 日:初始发布
- 2011 年 3 月 9 日:添加了
UserControl
- 2011 年 3 月 11 日:添加了
UserControl
的 v2 版本