チュートリアル: 初めてのタッチ アプリケーションの作成

WPF では、タッチに応答するアプリケーションを作成できます。 たとえば、タッチスクリーンなどのタッチを検知するデバイスで 1 本または複数本の指を使用してアプリケーションを操作できます。このチュートリアルでは、タッチすることで単一のオブジェクトを移動、サイズ変更または回転させることのできるアプリケーションを作成します。

前提条件

このチュートリアルを実行するには、次のコンポーネントが必要です。

  • Microsoft Visual Studio 2010.

  • Windows 7。

  • Windows タッチをサポートする、タッチスクリーンなどのタッチ入力ができるデバイス。

また、WPF でのアプリケーションの作成において、特にイベントのサブスクライブ方法と処理方法に関する基礎知識があることが必要です。 詳細については、「チュートリアル: WPF の概要」を参照してください。

アプリケーションの作成

アプリケーションを作成するには

  1. Visual Basic または Visual C# で、「BasicManipulation」という名前の新しい WPF アプリケーション プロジェクトを作成します。 詳細については、「方法 : 新しい WPF アプリケーション プロジェクトを作成する」を参照してください。

  2. MainWindow.xaml の内容を次の XAML に置き換えます。

    マークアップにより、Canvas 上に赤い Rectangle を含む単純なアプリケーションが作成されます。 RectangleIsManipulationEnabled プロパティは、操作イベントを受け取ることができるように true に設定されます。 アプリケーションは、ManipulationStarting イベント、ManipulationDelta イベントおよび ManipulationInertiaStarting イベントをサブスクライブします。 これらのイベントには、ユーザーが操作したときに 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 イベント ハンドラーを追加します。

    ManipulationStarting イベントは、WPF がタッチ入力によるオブジェクト操作の開始を検知すると発生します。 コードでは、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 イベントは慣性をシミュレートするために発生し続けます。

    コードでは、ユーザーのタッチ入力に沿って移動するために、RectangleRenderTransformDeltaManipulation を適用します。 また、慣性処理中にイベントが発生したときに、RectangleWindow の境界の外側にあるかどうかもチェックします。 境界の外側にある場合、アプリケーションは 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 の上に 1 本の指を置き、画面上でその指を動かします。

  • Rectangle のサイズを変更するには、Rectangle 上に 2 本の指を置き、指どうしの距離を互いに近づけるか離します。

  • Rectangle を回転させるには、Rectangle 上に 2 本の指を置き、互いの周りで指を回します。

慣性を発生させるには、直前の操作を実行したときに画面からすばやく指を離します。 Rectangle は、停止するまでの数秒間、移動、サイズ変更または回転を続けます。

参照

参照

UIElement.ManipulationStarting

UIElement.ManipulationDelta

UIElement.ManipulationInertiaStarting