演练:创建你的第一个触控应用程序Walkthrough: Creating Your First Touch Application

WPFWPF 使应用程序能够响应触摸。enables applications to respond to touch. 例如,可以使用一个与应用程序交互或敏式设备,如本演练中创建该应用程序,用户可以移动,触摸屏上的多个手指重设大小,或使用触摸来旋转的单个对象。For example, you can interact with an application by using one or more fingers on a touch-sensitive device, such as a touchscreen This walkthrough creates an application that enables the user to move, resize, or rotate a single object by using touch.

系统必备Prerequisites

你需要以下组件来完成本演练:You need the following components to complete this walkthrough:

  • Visual Studio。Visual Studio.

  • 接受触控输入,如触摸屏,支持 Windows 触摸设备。A device that accepts touch input, such as a touchscreen, that supports Windows Touch.

此外,应该基本了解如何创建中的应用程序的WPFWPF,尤其是如何订阅和处理事件。Additionally, you should have a basic understanding of how to create an application in WPFWPF, especially how to subscribe to and handle an event. 有关详细信息,请参见演练:我第一个 WPF 桌面应用程序For more information, see Walkthrough: My first WPF desktop application.

创建应用程序Creating the Application

创建应用程序To create the application

  1. 在 Visual Basic 或 Visual C# 中创建名为 BasicManipulation 的新 WPF 应用程序项目。Create a new WPF Application project in Visual Basic or Visual C# named BasicManipulation. 有关详细信息,请参见演练:我第一个 WPF 桌面应用程序For more information, see Walkthrough: My first WPF desktop application.

  2. MainWindow.xaml 的内容替换为以下 XAML。Replace the contents of MainWindow.xaml with the following XAML.

    此标记将创建一个简单的应用程序包含一个红色RectangleCanvasThis markup creates a simple application that contains a red Rectangle on a Canvas. IsManipulationEnabled属性的Rectangle设置为 true,以便它将接收操作事件。The IsManipulationEnabled property of the Rectangle is set to true so that it will receive manipulation events. 应用程序订阅ManipulationStartingManipulationDelta,和ManipulationInertiaStarting事件。The application subscribes to the ManipulationStarting, ManipulationDelta, and ManipulationInertiaStarting events. 这些事件包含的逻辑移动Rectangle用户处理。These events contain the logic to move the Rectangle when the user manipulates it.

    <Window x:Class="BasicManipulation.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://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"If you are using Visual Basic, in the first line of MainWindow.xaml, replace x:Class="BasicManipulation.MainWindow" with x:Class="MainWindow".

  4. 在中MainWindow类中,添加以下ManipulationStarting事件处理程序。In the MainWindow class, add the following ManipulationStarting event handler.

    ManipulationStarting事件发生时WPFWPF检测到触控输入开始操作对象。The ManipulationStarting event occurs when WPFWPF detects that touch input begins to manipulate an object. 该代码指定操作位置应为相对于Window通过设置ManipulationContainer属性。The code specifies that the position of the manipulation should be relative to the Window by setting the ManipulationContainer property.

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

    ManipulationDelta事件发生时触摸输入更改位置,并可在操作过程中出现多次。The ManipulationDelta event occurs when the touch input changes position and can occur multiple times during a manipulation. 引发一个手指后,也会发生该事件。The event can also occur after a finger is raised. 例如,如果用户在屏幕上拖动手指ManipulationDelta事件发生多次在手指移动时。For example, if the user drags a finger across a screen, the ManipulationDelta event occurs multiple times as the finger moves. 当用户将手指从屏幕上,ManipulationDelta事件会不断发生,以模拟惯性。When the user raises a finger from the screen, the ManipulationDelta event keeps occurring to simulate inertia.

    此代码适用DeltaManipulationRenderTransformRectangle可将其移动用户在将移动触控输入。The code applies the DeltaManipulation to the RenderTransform of the Rectangle to move it as the user moves the touch input. 它还会检查是否Rectangle的界限外Window在惯性期间在事件发生时。It also checks whether the Rectangle is outside the bounds of the Window when the event occurs during inertia. 因此,在应用程序调用ManipulationDeltaEventArgs.Complete方法来结束操作。If so, the application calls the ManipulationDeltaEventArgs.Complete method to end the manipulation.

    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;
    }
    
    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
    
  6. 在中MainWindow类中,添加以下ManipulationInertiaStarting事件处理程序。In the MainWindow class, add the following ManipulationInertiaStarting event handler.

    ManipulationInertiaStarting事件发生时用户将所有手指从屏幕。The ManipulationInertiaStarting event occurs when the user raises all fingers from the screen. 该代码设置初始速度和为移动、 扩展和旋转矩形的减速度。The code sets the initial velocity and deceleration for the movement, expansion, and rotation of the rectangle.

    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;
    }
    
    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
    
  7. 生成并运行该项目。Build and run the project.

    应会看到窗口中显示一个红色方块。You should see a red square appear in the window.

测试应用程序Testing the Application

若要测试应用程序,请尝试以下操作。To test the application, try the following manipulations. 请注意,您可以多个以下项之一在同一时间。Note that you can do more than one of the following at the same time.

  • 若要将移动Rectangle,将手指放Rectangle并在屏幕上移动手指。To move the Rectangle, put a finger on the Rectangle and move the finger across the screen.

  • 若要调整大小Rectangle,将两根手指放Rectangle,并将手指,或将其彼此相差。To resize the Rectangle, put two fingers on the Rectangle and move the fingers closer together or farther apart from each other.

  • 若要旋转Rectangle,将两根手指放Rectangle和旋转相对于每个其他手指。To rotate the Rectangle, put two fingers on the Rectangle and rotate the fingers around each other.

若要导致延时,快速提升您将手指从屏幕执行上一操作。To cause inertia, quickly raise your fingers from the screen as you perform the previous manipulations. Rectangle将继续移动、 调整大小,或为几秒钟才会停止旋转。The Rectangle will continue to move, resize, or rotate for a few seconds before it stops.

请参阅See also