Share via


演练:创建您的第一个触控应用程序

WPF 使应用程序可以对触控做出响应。 例如,您可以通过用一个或多个手指操纵触控敏感型设备(如触摸屏)来与应用程序交互。此演练将创建一个使用户可以使用触控功能移动、旋转一个对象或调整其大小的应用程序。

系统必备组件

您需要以下组件来完成本演练:

  • Microsoft Visual Studio 2010.

  • Windows 7。

  • 接受触控输入的设备,如支持 Windows 触摸屏技术的触摸屏。

此外,您应该大致了解如何在 WPF 中创建应用程序,尤其是如何订阅和处理事件。 有关更多信息,请参见 演练:开始使用 WPF

创建应用程序

创建应用程序

  1. 使用 Visual Basic 或 Visual C# 新建一个名为 BasicManipulation 的 WPF 应用程序项目。 有关更多信息,请参见如何:创建新的 WPF 应用程序项目

  2. 用以下 XAML 替换 MainWindow.xaml 的内容。

    此标记会创建一个在 Canvas 上包含红色 Rectangle 的简单应用程序。 RectangleIsManipulationEnabled 属性设置为 true,以使其可以接收操作事件。 该应用程序订阅 ManipulationStartingManipulationDeltaManipulationInertiaStarting 事件。 这些事件包含在用户操作 Rectangle 时对该形状进行移动的逻辑。

    <Window x:Class="BasicManipulation.MainWindow"
            xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
            Title="Move, Size, and Rotate the Square"
            WindowState="Maximized"
            ManipulationStarting="Window_ManipulationStarting"
            ManipulationDelta="Window_ManipulationDelta"
            ManipulationInertiaStarting="Window_InertiaStarting">
      <Window.Resources>
    
        <!--The movement, rotation, and size of the Rectangle is 
            specified by its RenderTransform.-->
        <MatrixTransform x:Key="InitialMatrixTransform">
          <MatrixTransform.Matrix>
            <Matrix OffsetX="200" OffsetY="200"/>
          </MatrixTransform.Matrix>
        </MatrixTransform>
    
      </Window.Resources>
    
      <Canvas>
        <Rectangle Fill="Red" Name="manRect"
                     Width="200" Height="200" 
                     RenderTransform="{StaticResource InitialMatrixTransform}"
                     IsManipulationEnabled="true" />
      </Canvas>
    </Window>
    
    
  3. 如果使用的是 Visual Basic,请在 MainWindow.xaml 的第一行中将 x:Class="BasicManipulation.MainWindow" 替换为 x:Class="MainWindow"。

  4. 在 MainWindow 类中,添加以下 ManipulationStarting 事件处理程序。

    当 WPF 检测到触控输入开始操作对象时,会发生 ManipulationStarting 事件。 该代码通过设置 ManipulationContainer 属性指定操作位置应相对于 Window

    Private Sub Window_ManipulationStarting(ByVal sender As Object, ByVal e As ManipulationStartingEventArgs)
        e.ManipulationContainer = Me
        e.Handled = True
    End Sub
    
    void Window_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
    {
        e.ManipulationContainer = this;
        e.Handled = true;
    }
    
  5. 在 MainWindow 类中,添加以下 ManipulationDelta 事件处理程序。

    ManipulationDelta 事件会在触控输入改变位置时发生,并且会在操作期间多次发生。 此事件还会在抬起手指后发生。 例如,如果用户在屏幕上拖动手指,则在手指移动时,会多次发生 ManipulationDelta 事件。 当用户将手指从屏幕上抬起时,ManipulationDelta 事件会不断发生以模拟惯性。

    该代码将 DeltaManipulation 应用到 RectangleRenderTransform 以在用户移动触控输入时移动该元素。 它还检查当在惯性期间发生该事件时 Rectangle 是否在 Window 的边界之外。 如果是,则应用程序会调用 ManipulationDeltaEventArgs.Complete 方法来结束操作。

    Private Sub Window_ManipulationDelta(ByVal sender As Object, ByVal e As ManipulationDeltaEventArgs)
    
        ' Get the Rectangle and its RenderTransform matrix.
        Dim rectToMove As Rectangle = e.OriginalSource
        Dim rectTransform As MatrixTransform = rectToMove.RenderTransform
        Dim rectsMatrix As Matrix = rectTransform.Matrix
    
    
        ' Rotate the shape
        rectsMatrix.RotateAt(e.DeltaManipulation.Rotation,
                             e.ManipulationOrigin.X,
                             e.ManipulationOrigin.Y)
    
        ' Resize the Rectangle. Keep it square 
        ' so use only the X value of Scale.
        rectsMatrix.ScaleAt(e.DeltaManipulation.Scale.X,
                            e.DeltaManipulation.Scale.X,
                            e.ManipulationOrigin.X,
                            e.ManipulationOrigin.Y)
    
        'move the center
        rectsMatrix.Translate(e.DeltaManipulation.Translation.X,
                              e.DeltaManipulation.Translation.Y)
    
        ' Apply the changes to the Rectangle.
        rectTransform = New MatrixTransform(rectsMatrix)
        rectToMove.RenderTransform = rectTransform
    
        Dim container As FrameworkElement = e.ManipulationContainer
        Dim containingRect As New Rect(container.RenderSize)
    
        Dim shapeBounds As Rect = rectTransform.TransformBounds(
                                    New Rect(rectToMove.RenderSize))
    
        ' Check if the rectangle is completely in the window.
        ' If it is not and intertia is occuring, stop the manipulation.
        If e.IsInertial AndAlso Not containingRect.Contains(shapeBounds) Then
            e.Complete()
        End If
    
        e.Handled = True
    End Sub
    
    void Window_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
    
        // Get the Rectangle and its RenderTransform matrix.
        Rectangle rectToMove = e.OriginalSource as Rectangle;
        Matrix rectsMatrix = ((MatrixTransform)rectToMove.RenderTransform).Matrix;
    
        // Rotate the Rectangle.
        rectsMatrix.RotateAt(e.DeltaManipulation.Rotation, 
                             e.ManipulationOrigin.X, 
                             e.ManipulationOrigin.Y);
    
        // Resize the Rectangle.  Keep it square 
        // so use only the X value of Scale.
        rectsMatrix.ScaleAt(e.DeltaManipulation.Scale.X, 
                            e.DeltaManipulation.Scale.X, 
                            e.ManipulationOrigin.X,
                            e.ManipulationOrigin.Y);
    
        // Move the Rectangle.
        rectsMatrix.Translate(e.DeltaManipulation.Translation.X,
                              e.DeltaManipulation.Translation.Y);
    
        // Apply the changes to the Rectangle.
        rectToMove.RenderTransform = new MatrixTransform(rectsMatrix);
    
        Rect containingRect =
            new Rect(((FrameworkElement)e.ManipulationContainer).RenderSize);
    
        Rect shapeBounds =
            rectToMove.RenderTransform.TransformBounds(
                new Rect(rectToMove.RenderSize));
    
        // Check if the rectangle is completely in the window.
        // If it is not and intertia is occuring, stop the manipulation.
        if (e.IsInertial && !containingRect.Contains(shapeBounds))
        {
            e.Complete();
        }
    
    
        e.Handled = true;
    }
    
  6. 在 MainWindow 类中,添加以下 ManipulationInertiaStarting 事件处理程序。

    当用户将所有手指从屏幕上抬起时,会发生 ManipulationInertiaStarting 事件。 该代码会为矩形的移动、展开和旋转设置初始速度和减速。

    Private Sub Window_InertiaStarting(ByVal sender As Object,
                                       ByVal e As ManipulationInertiaStartingEventArgs)
    
        ' Decrease the velocity of the Rectangle's movement by 
        ' 10 inches per second every second.
        ' (10 inches * 96 pixels per inch / 1000ms^2)
        e.TranslationBehavior.DesiredDeceleration = 10.0 * 96.0 / (1000.0 * 1000.0)
    
        ' Decrease the velocity of the Rectangle's resizing by 
        ' 0.1 inches per second every second.
        ' (0.1 inches * 96 pixels per inch / (1000ms^2)
        e.ExpansionBehavior.DesiredDeceleration = 0.1 * 96 / (1000.0 * 1000.0)
    
        ' Decrease the velocity of the Rectangle's rotation rate by 
        ' 2 rotations per second every second.
        ' (2 * 360 degrees / (1000ms^2)
        e.RotationBehavior.DesiredDeceleration = 720 / (1000.0 * 1000.0)
    
        e.Handled = True
    End Sub
    
    void Window_InertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)
    {
    
        // Decrease the velocity of the Rectangle's movement by 
        // 10 inches per second every second.
        // (10 inches * 96 pixels per inch / 1000ms^2)
        e.TranslationBehavior.DesiredDeceleration = 10.0 * 96.0 / (1000.0 * 1000.0);
    
        // Decrease the velocity of the Rectangle's resizing by 
        // 0.1 inches per second every second.
        // (0.1 inches * 96 pixels per inch / (1000ms^2)
        e.ExpansionBehavior.DesiredDeceleration = 0.1 * 96 / (1000.0 * 1000.0);
    
        // Decrease the velocity of the Rectangle's rotation rate by 
        // 2 rotations per second every second.
        // (2 * 360 degrees / (1000ms^2)
        e.RotationBehavior.DesiredDeceleration = 720 / (1000.0 * 1000.0);
    
        e.Handled = true;
    }
    
  7. 生成并运行该项目。

    您应该会看到窗口中显示一个红色的正方形。

测试应用程序

若要测试应用程序,请尝试执行下列操作。 请注意,您可以同时执行以下多项操作。

  • 若要移动 Rectangle,请将手指放在 Rectangle 上并在屏幕上移动手指。

  • 若要调整 Rectangle 的大小,请将两个手指放在 Rectangle 上,并将两个手指靠拢或将其分开。

  • 若要旋转 Rectangle,请将两个手指放在 Rectangle 上,然后将一个手指围绕另一个手指旋转。

若要产生惯性,请在执行前面的操作时快速将手指从屏幕上抬起。 Rectangle 将继续移动、调整大小或旋转几秒钟,然后再停止。

请参见

参考

UIElement.ManipulationStarting

UIElement.ManipulationDelta

UIElement.ManipulationInertiaStarting