65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 中的放大效果

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.38/5 (17投票s)

2011 年 3 月 8 日

CPOL

4分钟阅读

viewsIcon

82715

downloadIcon

5519

在 WPF 中创建放大效果以及如何使用我的放大镜控件

Screenshot_1.png

引言

本文的目的是让您了解如何在 WPF 应用程序中创建放大效果。希望您能从中掌握一些概念,这些概念将有助于您开发需要此类功能的完整应用程序。我还将解释如何使用我的 Magnifier 控件,这是一个 UserControl,其功能类似于具有放大区域的 Image 控件。

要求

要运行从上面的下载链接提供的项目,你需要以下之一

  • Visual Studio 2010
  • Expression Blend

如果您拥有 Visual Studio 2008,可以从 此处 下载源文件。

注意:如果您使用的是 Visual Studio 的 Express 版本,请确保使用 Visual Basic Express 打开解决方案。

Magnifier (演示)

工作原理

将鼠标指针移到图像上。将显示一个放大区域。移动鼠标可在图像周围移动放大区域。(如果您开始感到担忧,我敦促您不要担心。您应该看到别人的车。)

设计和布局

我将所有内容都放在 Expression Blend 中。下图显示了元素在“对象和时间轴”面板中的布局。

Layout.png

这里感兴趣的元素是 MainGridClipGrid,它们都是默认 LayoutRoot 的子元素。ClipGrid 实际上是 MainGrid 的一个副本,我只是在复制粘贴后重命名了它。两个 Grid 控件都有 Image 控件,这些控件具有相同的图像。

注意: ClipImageCursor 属性设置为“无”

CursorProperty.png

代码

我们有三个全局变量

    Private ClipRctGeo As New RectangleGeometry()
    Private ClipPath As New Path()
    Private ScaleTr As New ScaleTransform()

MainWindowInitialized 事件处理程序中,我们设置了这些对象的属性。

    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 定义了 RectangleGeometryClipRctGeo 的边框/描边颜色。老实说,我不知道 gainsboro 是什么,但它在浅色和深色背景上都效果很好。请注意,我们正在裁剪 Grid 控件 ClipGrid

MainGridMouseEnter 事件触发时,我们执行以下操作(请记住,在 MainWindowInitialized 事件期间,ClipGrid 已被裁剪,并且其 Visibility 属性设置为“隐藏”,而 ClipGridLayoutRoot 中堆叠在 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 对象 的中心点,以便“放大”从鼠标指针的位置发生,而鼠标指针是不可见的,因为我们将 ClipImageCursor 属性设置为 None。我敢肯定,您现在已经明白,通过缩放 ClipGrid,我们可以制造出图像被放大的错觉。

当调用 ClipGridMouseMove 事件处理程序时,放大区域会移动。

    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 控件的视在放大效果。

Screenshot_2.png

您可以从 此处 下载与上一个屏幕截图相关的演示。

Magnifier 控件

正如我在引言部分所解释的,Magnifier 控件的功能类似于具有放大区域的 Image 控件。要使用 Magnifier 控件,请添加对 Magnifier.dll 的引用,该文件可从上面的下载链接获取。该 DLL 应在项目“引用”文件夹中列出。

UserControlReferenced.png

激活“资产”面板,然后在搜索文本框中输入“magnifier”一词。键入前几个字母时,您应该会看到 Magnifier 控件显示出来。

AssetPanel.png

双击 Magnifier 控件将其添加到您的布局容器,或选择它并直接拖出。在“属性”面板的“Miscellaneous”部分,查找 ImagesSource 属性,然后单击省略号按钮,从您想要放置图像的位置选择一个图像。

ImagesSource.png

代码

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

ZoomScreenshot.png

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 版本
© . All rights reserved.