연습: 첫 응용 프로그램 만들기

WPF를 사용하여 응용 프로그램이 터치에 응답할 수 있습니다. 예를 들어 터치 스크린과 같은 터치 인식 장치에서 손가락을 사용하여 응용 프로그램과 상호 작용할 수 있습니다. 이 연습에서는 터치를 통해 단일 개체를 이동, 크기 조정 또는 회전할 수 있는 응용 프로그램을 만듭니다.

사전 요구 사항

이 연습을 완료하려면 다음 구성 요소가 필요합니다.

  • Microsoft Visual Studio 2010.

  • Windows 7

  • Windows Touch를 지원하는 터치 스크린과 같은 터치 입력을 허용하는 장치

또한 WPF에서 응용 프로그램을 만드는 방법 특히, 이벤트를 구독하고 처리하는 방법을 기본적으로 알고 있어야 합니다. 자세한 내용은 연습: WPF 시작을 참조하십시오.

응용 프로그램 만들기

응용 프로그램을 만들려면

  1. Visual Basic 또는 Visual C#에서 BasicManipulation이라는 새 WPF 응용 프로그램 프로젝트를 만듭니다. 자세한 내용은 방법: 새 WPF 응용 프로그램 프로젝트 만들기를 참조하십시오.

  2. MainWindow.xaml의 내용을 다음 XAML로 바꿉니다.

    이 태그는 Canvas에서 빨간색 Rectangle을 포함하는 간단한 응용 프로그램을 만듭니다. RectangleIsManipulationEnabled 속성은 조직 이벤트를 받도록 true로 설정되어 있습니다. 응용 프로그램에서는 ManipulationStarting, ManipulationDeltaManipulationInertiaStarting 이벤트를 구독합니다. 이러한 이벤트에는 사용자가 조작할 때 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 이벤트가 계속 발생하여 관성의 법칙을 시뮬레이션합니다.

    이 코드에서는 사용자의 터치 입력에 따라 이동하도록 DeltaManipulationRectangleRenderTransform에 적용합니다. 또한 관성의 법칙이 적용되는 동안 이벤트가 발생할 때 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에 손가락을 놓고 화면에서 손가락을 이동합니다.

  • Rectangle의 크기를 조정하려면 Rectangle에 두 손가락을 놓은 다음 손가락을 모으거나 벌립니다.

  • Rectangle을 회전하려면 Rectangle에 두 손가락을 놓고 손가락을 서로 회전시킵니다.

관성이 작용하도록 하려면 이전 조작을 수행하면서 화면에서 손가락을 빠르게 치웁니다. Rectangle이 2초 동안 계속 이동, 크기 조정 또는 회전하다가 멈춥니다.

참고 항목

참조

UIElement.ManipulationStarting

UIElement.ManipulationDelta

UIElement.ManipulationInertiaStarting