Пошаговое руководство. Создание первого приложения для обработки касаний

WPF позволяет приложениям реагировать на касания. Например, можно взаимодействовать с приложением, касаясь одним или несколькими пальцами сенсорного устройства, например сенсорного экрана. В этом пошаговом руководстве создается приложение, позволяющее пользователю с помощью касания перемещать и поворачивать одиночный объект или изменять его размер.

Необходимые компоненты

Для выполнения этого пошагового руководства требуются следующие компоненты:

  • Visual Studio.

  • Устройство, поддерживающее сенсорный ввод, например сенсорный экран.

Кроме того, необходимо иметь базовое представление о создании приложения в WPF, в частности о подписке на событие и о его обработке. Дополнительные сведения см. в разделе Пошаговое руководство. Создание первого классического приложения WPF.

Создание приложения

Создание приложения

  1. Создайте проект приложения WPF на Visual Basic или Visual C# с именем BasicManipulation. Дополнительные сведения см. в разделе Пошаговое руководство. Создание первого классического приложения WPF.

  2. Замените содержимое файла MainWindow.xaml следующим кодом XAML.

    Эта разметка создает простое приложение, содержащее красный прямоугольник Rectangle на холсте Canvas. Свойству IsManipulationEnabled объекта Rectangle присваивается значение true, чтобы оно получало события манипуляции. Приложение подписывается на события ManipulationStarting, ManipulationDelta и ManipulationInertiaStarting. Эти события содержат логику перемещения объекта Rectangle, когда пользователь что-то с ним делает.

    <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".

  4. Добавьте следующий обработчик события ManipulationStarting в классе MainWindow.

    Событие ManipulationStarting возникает, когда WPF обнаруживает, что сенсорный ввод начинает манипулировать объектом. Код, задавая свойство ManipulationContainer, определяет, что положение манипуляции должно задаваться относительно объекта Window.

    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. Добавьте следующий обработчик события ManipulationDelta в классе MainWindow.

    Событие ManipulationDelta возникает, когда сенсорный ввод меняет положение, и может возникать несколько раз во время манипуляции. Событие также может возникать после того, как будет убран палец. Например, если пользователь проводит пальцем по экрану, по мере перемещения пальца событие ManipulationDelta возникает несколько раз. Когда пользователь убирает палец с экрана, событие ManipulationDelta продолжает возникать для имитации инерции.

    Код применяет DeltaManipulation к RenderTransform прямоугольника Rectangle, чтобы перемещать его по ходу перемещения пользователем точки касания. Когда событие возникает во время инерции, код во время возникновения события также проверяет, не выходит ли прямоугольник Rectangle за границы окна Window. Если да, приложение вызывает метод ManipulationDeltaEventArgs.Complete для завершения манипуляции.

    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. Добавьте следующий обработчик события ManipulationInertiaStarting в классе MainWindow.

    Событие ManipulationInertiaStarting возникает, когда пользователь убирает все пальцы с экрана. Код задает начальную скорость и замедление перемещения, расширения и поворота прямоугольника.

    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. Постройте и запустите проект.

    В окне должен появиться красный квадрат.

Тестирование приложения

Для проверки работы приложения выполните следующие действия. Обратите внимание, что можно одновременно выполнить несколько из следующих действий.

  • Чтобы переместить Rectangle, коснитесь пальцем Rectangle и переместите палец по экрану.

  • Чтобы изменить размер Rectangle, поместите два пальца на Rectangle и сведите или разведите пальцы.

  • Чтобы повернуть Rectangle, поместите два пальца на Rectangle и поверните пальцы один вокруг другого.

Чтобы вызвать инерцию, быстро убирайте пальцы с экрана при выполнении предыдущих манипуляций. Rectangle продолжит перемещаться, менять размер или поворачиваться в течение нескольких секунд, прежде чем остановится.

См. также