언어: HTML | XAML

빠른 시작: 포인터(XAML)

Applies to Windows and Windows Phone

터치, 마우스 및 펜/스타일러스 조작은 C++, C# 또는 Visual Basic으로 작성한 Windows 런타임 앱에서 포인터 입력으로 수신, 처리 및 관리됩니다.

C++, C# 또는 Visual Basic을 사용하여 Windows 런타임 앱을 처음 개발하는 경우:  다음 항목을 검토하여 여기서 설명하는 기술에 대해 알아보세요.

C# 또는 Visual Basic을 사용하여 첫 Windows 스토어 앱 만들기

C++를 사용하여 첫 Windows 스토어 앱 만들기

C# 또는 Visual Basic으로 작성한 Windows 런타임 앱용 로드맵

C++로 작성한 Windows 런타임 앱용 로드맵

이벤트에 대한 자세한 내용은 이벤트 및 라우트된 이벤트 개요를 참조하세요.

앱 기능 전체 프로세스:  앱 기능 전체 프로세스 시리즈의 일부로 이 기능을 자세히 살펴보세요.

사용자 조작 전체 프로세스(XAML)

사용자 조작 사용자 지정 전체 프로세스(XAML)

사용자 환경 지침:  

플랫폼 컨트롤 라이브러리(HTMLXAML)는 표준 조작, 애니메이션 물리적 효과 및 시각적 피드백을 비롯하여 Windows 사용자 조작 환경 전체를 제공합니다. 사용자 지정 조작 지원이 필요 없는 경우에는 이러한 기본 제공 컨트롤을 사용하세요.

플랫폼 컨트롤이 충분하지 않으면 다음 사용자 조작 지침을 통해 입력 모드 전체에서 멋진 몰입형 조작 환경을 일관되게 제공합니다. 이러한 지침은 주로 터치식 입력을 중심으로 다루지만 터치 패드, 마우스, 키보드 및 스타일러스 입력에도 관련이 있습니다.

샘플:  이 기능의 작동 방식을 보려면 Windows 스토어 앱 샘플을 참조하세요.

입력: XAML 사용자 입력 이벤트 샘플

입력: 장치 접근 권한 값 샘플

입력: 조작 및 제스처(C++) 샘플

입력: 터치 적중 횟수 테스트 샘플

XAML 스크롤, 이동 및 확대/축소 샘플

입력: 간단한 잉크 샘플

목표: 포인터 입력을 수신하고 처리하는 방법에 대해 살펴봅니다.

사전 요구 사항

사용자가 C++, C# 또는 Visual Basic를 사용하여 기본 Windows 런타임 앱을 만들 수 있다고 가정합니다.

이 자습서를 완료하려면 다음을 수행해야 합니다.

완료 시간: 30 분.

지침

포인터 입력이란?

마우스, 펜/스타일러스 및 터치 입력을 추상 포인터 입력으로 통합하여 사용 중인 입력 장치 유형과는 별개로 앱의 사용자 조작을 처리할 수 있습니다.

Pointer 개체는 입력 장치(예: 마우스, 펜/스타일러스, 한 손가락 또는 여러 손가락)의 고유한 단일 입력 접촉을 나타냅니다. 시스템에서는 처음 접촉이 감지될 때 포인터를 만들고, 포인터가 감지 범위를 벗어나거나(분리) 취소될 때 포인터를 삭제합니다. 여러 장치 또는 멀티 터치 입력의 경우 각 접점이 하나의 고유한 포인터로 간주됩니다.

다양한 장치에서 직접 입력 데이터를 가로챌 수 있는 포인터 기반 입력 API는 다양합니다. 범위 또는 접촉의 감지 상태와 장치 유형과 같은 기본 정보, 그리고 위치, 압력 및 접촉 기하학적 구조와 같은 확장된 정보를 가져올 수 있도록 포인터 이벤트를 처리할 수 있습니다. 앱이 다양한 방법으로 서로 다른 입력 모드에 응답해야 하는 경우가 많기 때문에 사용자가 입력하는 마우스 단추 또는 사용자의 펜 지우개 설명 사용 여부와 같은 특정 장치 속성도 사용할 수 있습니다. 예를 들어 터치 방식에서 이동 및 스크롤과 같은 조작을 지원하도록 할 수 있지만 마우스 및 펜/스타일러스는 잉크 및 그리기와 같은 작업에 좀 더 적합합니다. 앱에서 입력 장치와 해당 접근 권한 값을 구분해야 할 경우에는 빠른 시작: 입력 장치 식별을 참조하세요.

고유한 조작 지원을 구현하는 경우 사용자들은 앱의 UI 요소를 직접 조작하는 직관적인 환경을 기대한다는 것에 유의하세요. 플랫폼 컨트롤 라이브러리(HTMLXAML)에서 항목이 일관되고 검색 가능하도록 사용자 지정 조작을 모델링하는 것이 좋습니다. 이러한 라이브러리의 컨트롤은 표준 조작, 애니메이션 효과를 준 물리적 효과, 시각적 피드백 및 접근성을 비롯하여 Windows 8.1 사용자 조작 환경 전체를 제공합니다. 요구 사항이 명확하게 잘 정의되어 있으며 기본 제스처가 시나리오를 지원하지 않는 경우에만 사용자 지정 조작을 만드세요.

UI 만들기

다음 예에서는 직사각형(targetContainer)을 포인터 입력을 위한 대상 개체로 사용합니다. 대상의 색상은 포인터 상태가 변경될 때 변경됩니다.

각 포인터에 대한 상세 정보는 직사각형 아래에 표시되며, 포인터 이벤트 자체는 직사각형의 왼쪽에 표시됩니다(이벤트 순서 보고용).

다음은 XAML(Extensible Application Markup Language) 예문입니다.


    <Page
    x:Class="PointerInput.MainPage"
    IsTabStop="false"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PointerInput"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Name="page">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="150" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="320" />
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Canvas Name="Container" 
                Grid.Column="0"
                Grid.Row="1"
                HorizontalAlignment="Center" 
                VerticalAlignment="Center" 
                Margin="0,0,0,0" 
                Height="320"  Width="640">
            <Rectangle Name="Target" 
                       Fill="#FF0000" 
                       Stroke="Black" 
                       StrokeThickness="0"
                       Height="320" Width="640" />
        </Canvas>
        <TextBox Name="eventLog" 
                 Grid.Column="1"
                 Grid.Row="0"
                 Grid.RowSpan="3" 
                 Background="#000000" 
                 TextWrapping="Wrap" 
                 Foreground="#FFFFFF" 
                 ScrollViewer.VerticalScrollBarVisibility="Visible" 
                 BorderThickness="0"/>
    </Grid>
</Page>


포인터 이벤트 수신

대부분의 경우 선택한 Windows 8 언어 프레임워크(JavaScript로 작성한 Windows 런타임 앱, C++, C# 또는 Visual Basic으로 작성한 Windows 런타임 앱 또는 DirectX 및 C++로 작성한 Windows 스토어 앱)에서 포인터 이벤트 처리기의 이벤트 인수를 통해 포인터 정보를 가져오는 것이 좋습니다.

이벤트 인수가 본질적으로 앱에 필요한 포인터 정보를 표시하지 않으면 PointerRoutedEventArgsGetCurrentPointGetIntermediatePoints 메서드를 통해 PointerPoint 개체가 표시하는 확장된 포인터 데이터에 액세스할 수 있습니다.

다음 예에서는 직사각형(targetContainer)을 포인터 입력을 위한 대상 개체로 사용합니다. 대상의 색상은 포인터 상태가 변경될 때 변경됩니다.

각 포인터에 대한 상세 정보는 포인터와 연결된 부동 텍스트 블록에 표시되며, 포인터 이벤트 자체는 직사각형의 오른쪽에 표시됩니다(이벤트 순서 보고용).

다음 코드는 대상 개체를 설정하고, 전역 변수를 선언하고, 대상에 대해 다양한 포인터 이벤트 수신기를 식별합니다.


        // For this example, we track simultaneous contacts in case the 
        // number of contacts has reached the maximum supported by the device.
        // Depending on the device, additional contacts might be ignored 
        // (PointerPressed not fired). 
        uint numActiveContacts;
        Windows.Devices.Input.TouchCapabilities touchCapabilities = new Windows.Devices.Input.TouchCapabilities();

        // Dictionary to maintain information about each active contact. 
        // An entry is added during PointerPressed/PointerEntered events and removed 
        // during PointerReleased/PointerCaptureLost/PointerCanceled/PointerExited events.
        Dictionary<uint, Windows.UI.Xaml.Input.Pointer> contacts;

        public MainPage()
        {
            this.InitializeComponent();
            numActiveContacts = 0;
            // Initialize the dictionary.
            contacts = new Dictionary<uint, Windows.UI.Xaml.Input.Pointer>((int)touchCapabilities.Contacts);
            // Declare the pointer event handlers.
            Target.PointerPressed += new PointerEventHandler(Target_PointerPressed);
            Target.PointerEntered += new PointerEventHandler(Target_PointerEntered);
            Target.PointerReleased += new PointerEventHandler(Target_PointerReleased);
            Target.PointerExited += new PointerEventHandler(Target_PointerExited);
            Target.PointerCanceled += new PointerEventHandler(Target_PointerCanceled);
            Target.PointerCaptureLost += new PointerEventHandler(Target_PointerCaptureLost);
            Target.PointerMoved += new PointerEventHandler(Target_PointerMoved);
            Target.PointerWheelChanged += new PointerEventHandler(Target_PointerWheelChanged);
        }



포인터 이벤트 처리

다음으로 UI 피드백을 사용하여 기본 포인터 이벤트 처리기에 대해 살펴봅니다.

  • 이 처리기는 포인터 접촉 이벤트(아래로, 누름) 이벤트를 관리합니다. 이벤트 로그에 이벤트를 추가하고, 관심있는 포인터를 추적하는 데 사용하는 포인터 배열에 포인터를 추가하고, 포인터 상세 정보를 표시합니다.

    참고  PointerPressedPointerReleased 이벤트는 항상 쌍으로 발생하지는 않습니다. 앱은 포인터 다운 작업(예: PointerExited, PointerCanceledPointerCaptureLost)을 완료할 수도 있는 이벤트를 수신하고 처리해야 합니다.

    
            // PointerPressed and PointerReleased events do not always occur in pairs. 
            // Your app should listen for and handle any event that might conclude a pointer down action 
            // (such as PointerExited, PointerCanceled, and PointerCaptureLost).
            // For this example, we track the number of contacts in case the 
            // number of contacts has reached the maximum supported by the device.
            // Depending on the device, additional contacts might be ignored 
            // (PointerPressed not fired). 
            void Target_PointerPressed(object sender, PointerRoutedEventArgs e)
            {
                if (Convert.ToBoolean(touchCapabilities.TouchPresent) && (numActiveContacts > touchCapabilities.Contacts))
                {
                    // Number of supported contacts exceeded.
                    return;
                }
    
                Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
    
                // Update event sequence.
                eventLog.Text += "\nDown: " + ptr.PointerId;
    
                // Change background color of target when pointer contact detected.
                Target.Fill = new SolidColorBrush(Windows.UI.Colors.Green);
    
                // Check if pointer already exists (for example, enter occurred prior to press).
                if (contacts.ContainsKey(ptr.PointerId))
                {
                    return;
                }
                // Add contact to dictionary.
                contacts[ptr.PointerId] = ptr;
                ++numActiveContacts;
    
                // Prevent most handlers along the event route from handling the same event again.
                e.Handled = true;
    
                // Display pointer details.
                createInfoPop(e);
            }
    
    
    
  • 다음 처리기는 포인터 진입(위로, 펜 호버) 이벤트를 관리합니다. 이벤트 로그에 이벤트를 추가하고, 포인터 모음에 포인터를 추가하고, 포인터 상세 정보를 표시합니다.

    
            private void Target_PointerEntered(object sender, PointerRoutedEventArgs e)
            {
                Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
    
                // Update event sequence.
                eventLog.Text += "\nOver: " + ptr.PointerId;
    
                if (contacts.Count == 0)
                {
                    // Change background color of target when pointer contact detected.
                    Target.Fill = new SolidColorBrush(Windows.UI.Colors.Blue);
                }
    
                // Check if pointer already exists (if enter occurred prior to down).
                if (contacts.ContainsKey(ptr.PointerId))
                {
                    return;
                }
    
                // Add contact to dictionary.
                contacts[ptr.PointerId] = ptr;
                ++numActiveContacts;
    
                // Prevent most handlers along the event route from handling the same event again.
                e.Handled = true;
    
                // Display pointer details.
                createInfoPop(e);
            }
    
    
    
  • 다음 처리기는 포인터 이동 이벤트를 관리합니다. 이벤트 로그에 이벤트를 추가하고 포인터 상세 정보를 업데이트합니다.

    중요  마우스 입력이 먼저 검색되면 마우스 입력이 할당된 단일 포인터와 연결됩니다. 마우스 단추(왼쪽, 휠 또는 오른쪽)를 클릭하면 PointerPressed 이벤트를 통해 포인터와 해당 단추 간의 보조 연결이 만들어집니다. PointerReleased 이벤트는 해당하는 동일한 마우스 단추를 해제한 경우에만 발생합니다(이 이벤트가 완료될 때까지는 다른 단추를 이 포인터와 연결할 수 없음). 이 독점적인 연결 때문에 다른 마우스 단추 클릭은 PointerMoved 이벤트를 통해 라우팅됩니다.

    
    private void Target_PointerMoved(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
    
        // Multiple, simultaneous mouse button inputs are processed here.
        // Mouse input is associated with a single pointer assigned when 
        // mouse input is first detected. 
        // Clicking additional mouse buttons (left, wheel, or right) during 
        // the interaction creates secondary associations between those buttons 
        // and the pointer through the pointer pressed event. 
        // The pointer released event is fired only when the last mouse button 
        // associated with the interaction (not necessarily the initial button) 
        // is released. 
        // Because of this exclusive association, other mouse button clicks are 
        // routed through the pointer move event.          
        if (ptr.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
        {
            // To get mouse state, we need extended pointer details.
            // We get the pointer info through the getCurrentPoint method
            // of the event argument. 
            Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(Target);
            if (ptrPt.Properties.IsLeftButtonPressed)
            {
                eventLog.Text += "\nLeft button: " + ptrPt.PointerId;
            }
            if (ptrPt.Properties.IsMiddleButtonPressed)
            {
                eventLog.Text += "\nWheel button: " + ptrPt.PointerId;
            }
            if (ptrPt.Properties.IsRightButtonPressed)
            {
                eventLog.Text += "\nRight button: " + ptrPt.PointerId;
            }
        }
    
        // Prevent most handlers along the event route from handling the same event again.
        e.Handled = true;
    
        // Display pointer details.
        updateInfoPop(e);
    }
    
    
    
  • 다음 처리기는 마우스 휠 이벤트(회전)를 관리합니다. 이벤트 로그에 이벤트를 추가하고, 포인터 배열에 포인터를 추가(필요한 경우)하고, 포인터 상세 정보를 표시합니다.

    
    private void Target_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
    
        // Update event sequence.
        eventLog.Text += "\nMouse wheel: " + ptr.PointerId;
    
        // Check if pointer already exists (for example, enter occurred prior to wheel).
        if (contacts.ContainsKey(ptr.PointerId))
        {
            return;
        }
    
        // Add contact to dictionary.
        contacts[ptr.PointerId] = ptr;
        ++numActiveContacts;
    
        // Prevent most handlers along the event route from handling the same event again.
        e.Handled = true;
    
        // Display pointer details.
        createInfoPop(e);
    }
    
    
    
  • 다음 처리기는 디지타이저와의 접촉이 종료되는 포인터 출발(들어 올리기, 위로) 이벤트를 관리합니다. 이벤트 로그에 이벤트를 추가하고, 포인터 모음에서 포인터를 제거하고, 포인터 상세 정보를 업데이트합니다.

    
    void Target_PointerReleased(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
    
        // Update event sequence.
        eventLog.Text += "\nUp: " + ptr.PointerId;
    
        // If event source is mouse pointer and the pointer is still 
        // over the target, retain pointer and pointer details.
        // Return without removing pointer from pointers dictionary.
        // For this example, we assume a maximum of one mouse pointer.
        if (ptr.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
        {
            Target.Fill = new SolidColorBrush(Windows.UI.Colors.Blue);
            return;
        }
    
        // Update target UI.
        Target.Fill = new SolidColorBrush(Windows.UI.Colors.Red);
    
    
        destroyInfoPop(ptr);
    
        // Remove contact from dictionary.
        if (contacts.ContainsKey(ptr.PointerId))
        {
            contacts[ptr.PointerId] = null;
            contacts.Remove(ptr.PointerId);
            --numActiveContacts;
        }
        // Prevent most handlers along the event route from handling the same event again.
        e.Handled = true;
    }
    
    
    
  • 다음 처리기는 디지타이저와의 접촉이 종료되는 포인터 출발(외부) 이벤트를 관리합니다. 이벤트 로그에 이벤트를 추가하고, 포인터 배열에서 포인터를 제거하고, 포인터 상세 정보를 업데이트합니다.

    
    private void Target_PointerExited(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
    
        // Update event sequence.
        eventLog.Text += "\nPointer exited: " + ptr.PointerId;
    
        // Remove contact from dictionary.
        if (contacts.ContainsKey(ptr.PointerId))
        {
            contacts[ptr.PointerId] = null;
            contacts.Remove(ptr.PointerId);
            --numActiveContacts;
        }
    
        // Update the UI and pointer details.
        destroyInfoPop(ptr);
    
        if (contacts.Count == 0)
        {
            Target.Fill = new SolidColorBrush(Windows.UI.Colors.Red);
        }
        // Prevent most handlers along the event route from handling the same event again.
        e.Handled = true;
    }
    
    
    
  • 다음 처리기는 포인터 취소 이벤트를 관리합니다. 이벤트 로그에 이벤트를 추가하고, 포인터 배열에서 포인터를 제거하고, 포인터 상세 정보를 업데이트합니다.

    
    // Fires for for various reasons, including: 
    //    - Touch contact canceled by pen coming into range of the surface.
    //    - The device doesn't report an active contact for more than 100ms.
    //    - The desktop is locked or the user logged off. 
    //    - The number of simultaneous contacts exceeded the number supported by the device.
    private void Target_PointerCanceled(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
    
        // Update event sequence.
        eventLog.Text += "\nPointer canceled: " + ptr.PointerId;
    
        // Remove contact from dictionary.
        if (contacts.ContainsKey(ptr.PointerId))
        {
            contacts[ptr.PointerId] = null;
            contacts.Remove(ptr.PointerId);
            --numActiveContacts;
        }
    
        destroyInfoPop(ptr);
    
        if (contacts.Count == 0)
        {
            Target.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
        }
        // Prevent most handlers along the event route from handling the same event again.
        e.Handled = true;
    }
    
    
    
  • 다음 처리기는 손실된 포인터 캡처 이벤트를 관리합니다. 이벤트 로그에 이벤트를 추가하고, 포인터 배열에서 포인터를 제거하고, 포인터 상세 정보를 업데이트합니다.

    참고  PointerCaptureLostPointerReleased 대신 발생할 수 있습니다. 포인터 캡처는 사용자 조작으로 인해 손실되거나, 다른 포인터를 프로그래밍 방식으로 캡처했거나 현재 포인터 캡처를 고의로 해지했기 때문에 손실될 수 있습니다.

    
    // Fires for for various reasons, including: 
    //    - User interactions
    //    - Programmatic capture of another pointer
    //    - Captured pointer was deliberately released
    // PointerCaptureLost can fire instead of PointerReleased. 
    private void Target_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
    
        // Update event sequence.
        eventLog.Text += "\nPointer capture lost: " + ptr.PointerId;
    
        // Remove contact from dictionary.
        if (contacts.ContainsKey(ptr.PointerId))
        {
            contacts[ptr.PointerId] = null;
            contacts.Remove(ptr.PointerId);
            --numActiveContacts;
        }
    
        destroyInfoPop(ptr);
    
        if (contacts.Count == 0)
        {
            Target.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
        }
        // Prevent most handlers along the event route from handling the same event again.
        e.Handled = true;
    }
    
    
    

포인터 속성 가져오기

앞에서 설명한 대로 앱에 사용하기 위해 선택하는 언어 프레임워크는 포인터 속성을 가져오는 방법을 제어합니다. C++, C# 또는 Visual Basic으로 작성한 Windows 런타임 앱은 PointerRoutedEventArgsGetCurrentPointGetIntermediatePoints 메서드를 통해 가져온 Windows.UI.Input.PointerPoint 개체를 통해 가장 확장된 포인터 정보를 가져와야 합니다.

  • 먼저 포인터별로 새로운 TextBlock을 만듭니다.

    
            void createInfoPop(PointerRoutedEventArgs e)
            {
                TextBlock pointerDetails = new TextBlock();
                Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(Target);
                pointerDetails.Name = ptrPt.PointerId.ToString();
                pointerDetails.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
                pointerDetails.Text = queryPointer(ptrPt);
    
                TranslateTransform x = new TranslateTransform();
                x.X = ptrPt.Position.X + 20;
                x.Y = ptrPt.Position.Y + 20;
                pointerDetails.RenderTransform = x;
    
                Container.Children.Add(pointerDetails);
            }
    
    
    
  • 그런 다음 해당 포인터와 연결된 기존의 TextBlock에서 포인터 정보를 업데이트하는 방법을 제공합니다.

    
            void updateInfoPop(PointerRoutedEventArgs e)
            {
                foreach (var pointerDetails in Container.Children)
                {
                    if (pointerDetails.GetType().ToString() == "Windows.UI.Xaml.Controls.TextBlock")
                    {
                        TextBlock _TextBlock = (TextBlock)pointerDetails;
                        if (_TextBlock.Name == e.Pointer.PointerId.ToString())
                        {
                            // To get pointer location details, we need extended pointer info.
                            // We get the pointer info through the getCurrentPoint method
                            // of the event argument. 
                            Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(Target);
                            TranslateTransform x = new TranslateTransform();
                            x.X = ptrPt.Position.X + 20;
                            x.Y = ptrPt.Position.Y + 20;
                            pointerDetails.RenderTransform = x;
                            _TextBlock.Text = queryPointer(ptrPt);
                        }
                    }
                }
            }
    
    
    
  • 마지막으로 다양한 포인터 속성을 쿼리합니다.

    
             String queryPointer(PointerPoint ptrPt)
             {
                 String details = "";
    
                 switch (ptrPt.PointerDevice.PointerDeviceType)
                 {
                     case Windows.Devices.Input.PointerDeviceType.Mouse:
                         details += "\nPointer type: mouse";
                         break;
                     case Windows.Devices.Input.PointerDeviceType.Pen:
                         details += "\nPointer type: pen";
                         if (ptrPt.IsInContact)
                         {
                             details += "\nPressure: " + ptrPt.Properties.Pressure;
                             details += "\nrotation: " + ptrPt.Properties.Orientation;
                             details += "\nTilt X: " + ptrPt.Properties.XTilt;
                             details += "\nTilt Y: " + ptrPt.Properties.YTilt;
                             details += "\nBarrel button pressed: " + ptrPt.Properties.IsBarrelButtonPressed;
                         }
                         break;
                     case Windows.Devices.Input.PointerDeviceType.Touch:
                         details += "\nPointer type: touch";
                         details += "\nrotation: " + ptrPt.Properties.Orientation;
                         details += "\nTilt X: " + ptrPt.Properties.XTilt;
                         details += "\nTilt Y: " + ptrPt.Properties.YTilt;
                         break;
                     default:
                         details += "\nPointer type: n/a";
                         break;
                 }
    
                 GeneralTransform gt = Target.TransformToVisual(page);
                 Point screenPoint;
    
                 screenPoint = gt.TransformPoint(new Point(ptrPt.Position.X, ptrPt.Position.Y));
                 details += "\nPointer Id: " + ptrPt.PointerId.ToString() +
                     "\nPointer location (parent): " + ptrPt.Position.X + ", " + ptrPt.Position.Y +
                     "\nPointer location (screen): " + screenPoint.X + ", " + screenPoint.Y;
                 return details;
             }
    
    
    

전체 예제

다음은 C# 코드 예제입니다. 좀 더 복잡한 샘플 링크는 이 페이지 하단에 있는 관련 항목을 참조하세요.


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace PointerInput
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        // For this example, we track simultaneous contacts in case the 
        // number of contacts has reached the maximum supported by the device.
        // Depending on the device, additional contacts might be ignored 
        // (PointerPressed not fired). 
        uint numActiveContacts;
        Windows.Devices.Input.TouchCapabilities touchCapabilities = new Windows.Devices.Input.TouchCapabilities();

        // Dictionary to maintain information about each active contact. 
        // An entry is added during PointerPressed/PointerEntered events and removed 
        // during PointerReleased/PointerCaptureLost/PointerCanceled/PointerExited events.
        Dictionary<uint, Windows.UI.Xaml.Input.Pointer> contacts;

        public MainPage()
        {
            this.InitializeComponent();
            numActiveContacts = 0;
            // Initialize the dictionary.
            contacts = new Dictionary<uint, Windows.UI.Xaml.Input.Pointer>((int)touchCapabilities.Contacts);
            // Declare the pointer event handlers.
            Target.PointerPressed += new PointerEventHandler(Target_PointerPressed);
            Target.PointerEntered += new PointerEventHandler(Target_PointerEntered);
            Target.PointerReleased += new PointerEventHandler(Target_PointerReleased);
            Target.PointerExited += new PointerEventHandler(Target_PointerExited);
            Target.PointerCanceled += new PointerEventHandler(Target_PointerCanceled);
            Target.PointerCaptureLost += new PointerEventHandler(Target_PointerCaptureLost);
            Target.PointerMoved += new PointerEventHandler(Target_PointerMoved);
            Target.PointerWheelChanged += new PointerEventHandler(Target_PointerWheelChanged);
        }


        // PointerPressed and PointerReleased events do not always occur in pairs. 
        // Your app should listen for and handle any event that might conclude a pointer down action 
        // (such as PointerExited, PointerCanceled, and PointerCaptureLost).
        // For this example, we track the number of contacts in case the 
        // number of contacts has reached the maximum supported by the device.
        // Depending on the device, additional contacts might be ignored 
        // (PointerPressed not fired). 
        void Target_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            if (Convert.ToBoolean(touchCapabilities.TouchPresent) && (numActiveContacts > touchCapabilities.Contacts))
            {
                // Number of supported contacts exceeded.
                return;
            }

            Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;

            // Update event sequence.
            eventLog.Text += "\nDown: " + ptr.PointerId;

            // Change background color of target when pointer contact detected.
            Target.Fill = new SolidColorBrush(Windows.UI.Colors.Green);

            // Check if pointer already exists (for example, enter occurred prior to press).
            if (contacts.ContainsKey(ptr.PointerId))
            {
                return;
            }
            // Add contact to dictionary.
            contacts[ptr.PointerId] = ptr;
            ++numActiveContacts;

            // Prevent most handlers along the event route from handling the same event again.
            e.Handled = true;

            // Display pointer details.
            createInfoPop(e);
        }

        void Target_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;

            // Update event sequence.
            eventLog.Text += "\nUp: " + ptr.PointerId;

            // If event source is mouse pointer and the pointer is still 
            // over the target, retain pointer and pointer details.
            // Return without removing pointer from pointers dictionary.
            // For this example, we assume a maximum of one mouse pointer.
            if (ptr.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
            {
                Target.Fill = new SolidColorBrush(Windows.UI.Colors.Blue);
                return;
            }

            // Update target UI.
            Target.Fill = new SolidColorBrush(Windows.UI.Colors.Red);


            destroyInfoPop(ptr);

            // Remove contact from dictionary.
            if (contacts.ContainsKey(ptr.PointerId))
            {
                contacts[ptr.PointerId] = null;
                contacts.Remove(ptr.PointerId);
                --numActiveContacts;
            }
            // Prevent most handlers along the event route from handling the same event again.
            e.Handled = true;
        }

        private void Target_PointerMoved(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;

            // Multiple, simultaneous mouse button inputs are processed here.
            // Mouse input is associated with a single pointer assigned when 
            // mouse input is first detected. 
            // Clicking additional mouse buttons (left, wheel, or right) during 
            // the interaction creates secondary associations between those buttons 
            // and the pointer through the pointer pressed event. 
            // The pointer released event is fired only when the last mouse button 
            // associated with the interaction (not necessarily the initial button) 
            // is released. 
            // Because of this exclusive association, other mouse button clicks are 
            // routed through the pointer move event.          
            if (ptr.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
            {
                // To get mouse state, we need extended pointer details.
                // We get the pointer info through the getCurrentPoint method
                // of the event argument. 
                Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(Target);
                if (ptrPt.Properties.IsLeftButtonPressed)
                {
                    eventLog.Text += "\nLeft button: " + ptrPt.PointerId;
                }
                if (ptrPt.Properties.IsMiddleButtonPressed)
                {
                    eventLog.Text += "\nWheel button: " + ptrPt.PointerId;
                }
                if (ptrPt.Properties.IsRightButtonPressed)
                {
                    eventLog.Text += "\nRight button: " + ptrPt.PointerId;
                }
            }

            // Prevent most handlers along the event route from handling the same event again.
            e.Handled = true;

            // Display pointer details.
            updateInfoPop(e);
        }

        private void Target_PointerEntered(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;

            // Update event sequence.
            eventLog.Text += "\nOver: " + ptr.PointerId;

            if (contacts.Count == 0)
            {
                // Change background color of target when pointer contact detected.
                Target.Fill = new SolidColorBrush(Windows.UI.Colors.Blue);
            }

            // Check if pointer already exists (if enter occurred prior to down).
            if (contacts.ContainsKey(ptr.PointerId))
            {
                return;
            }

            // Add contact to dictionary.
            contacts[ptr.PointerId] = ptr;
            ++numActiveContacts;

            // Prevent most handlers along the event route from handling the same event again.
            e.Handled = true;

            // Display pointer details.
            createInfoPop(e);
        }

        private void Target_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;

            // Update event sequence.
            eventLog.Text += "\nMouse wheel: " + ptr.PointerId;

            // Check if pointer already exists (for example, enter occurred prior to wheel).
            if (contacts.ContainsKey(ptr.PointerId))
            {
                return;
            }

            // Add contact to dictionary.
            contacts[ptr.PointerId] = ptr;
            ++numActiveContacts;

            // Prevent most handlers along the event route from handling the same event again.
            e.Handled = true;

            // Display pointer details.
            createInfoPop(e);
        }

        // Fires for for various reasons, including: 
        //    - User interactions
        //    - Programmatic capture of another pointer
        //    - Captured pointer was deliberately released
        // PointerCaptureLost can fire instead of PointerReleased. 
        private void Target_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;

            // Update event sequence.
            eventLog.Text += "\nPointer capture lost: " + ptr.PointerId;

            // Remove contact from dictionary.
            if (contacts.ContainsKey(ptr.PointerId))
            {
                contacts[ptr.PointerId] = null;
                contacts.Remove(ptr.PointerId);
                --numActiveContacts;
            }

            destroyInfoPop(ptr);

            if (contacts.Count == 0)
            {
                Target.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
            }
            // Prevent most handlers along the event route from handling the same event again.
            e.Handled = true;
        }

        // Fires for for various reasons, including: 
        //    - Touch contact canceled by pen coming into range of the surface.
        //    - The device doesn't report an active contact for more than 100ms.
        //    - The desktop is locked or the user logged off. 
        //    - The number of simultaneous contacts exceeded the number supported by the device.
        private void Target_PointerCanceled(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;

            // Update event sequence.
            eventLog.Text += "\nPointer canceled: " + ptr.PointerId;

            // Remove contact from dictionary.
            if (contacts.ContainsKey(ptr.PointerId))
            {
                contacts[ptr.PointerId] = null;
                contacts.Remove(ptr.PointerId);
                --numActiveContacts;
            }

            destroyInfoPop(ptr);

            if (contacts.Count == 0)
            {
                Target.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
            }
            // Prevent most handlers along the event route from handling the same event again.
            e.Handled = true;
        }

        private void Target_PointerExited(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;

            // Update event sequence.
            eventLog.Text += "\nPointer exited: " + ptr.PointerId;

            // Remove contact from dictionary.
            if (contacts.ContainsKey(ptr.PointerId))
            {
                contacts[ptr.PointerId] = null;
                contacts.Remove(ptr.PointerId);
                --numActiveContacts;
            }

            // Update the UI and pointer details.
            destroyInfoPop(ptr);

            if (contacts.Count == 0)
            {
                Target.Fill = new SolidColorBrush(Windows.UI.Colors.Red);
            }
            // Prevent most handlers along the event route from handling the same event again.
            e.Handled = true;
        }

        void createInfoPop(PointerRoutedEventArgs e)
        {
            TextBlock pointerDetails = new TextBlock();
            Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(Target);
            pointerDetails.Name = ptrPt.PointerId.ToString();
            pointerDetails.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
            pointerDetails.Text = queryPointer(ptrPt);

            TranslateTransform x = new TranslateTransform();
            x.X = ptrPt.Position.X + 20;
            x.Y = ptrPt.Position.Y + 20;
            pointerDetails.RenderTransform = x;

            Container.Children.Add(pointerDetails);
        }

        void destroyInfoPop(Windows.UI.Xaml.Input.Pointer ptr)
        {
            foreach (var pointerDetails in Container.Children)
            {
                if (pointerDetails.GetType().ToString() == "Windows.UI.Xaml.Controls.TextBlock")
                {
                    TextBlock _TextBlock = (TextBlock)pointerDetails;
                    if (_TextBlock.Name == ptr.PointerId.ToString())
                    {
                        Container.Children.Remove(pointerDetails);
                    }
                }
            }
        }

        void updateInfoPop(PointerRoutedEventArgs e)
        {
            foreach (var pointerDetails in Container.Children)
            {
                if (pointerDetails.GetType().ToString() == "Windows.UI.Xaml.Controls.TextBlock")
                {
                    TextBlock _TextBlock = (TextBlock)pointerDetails;
                    if (_TextBlock.Name == e.Pointer.PointerId.ToString())
                    {
                        // To get pointer location details, we need extended pointer info.
                        // We get the pointer info through the getCurrentPoint method
                        // of the event argument. 
                        Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(Target);
                        TranslateTransform x = new TranslateTransform();
                        x.X = ptrPt.Position.X + 20;
                        x.Y = ptrPt.Position.Y + 20;
                        pointerDetails.RenderTransform = x;
                        _TextBlock.Text = queryPointer(ptrPt);
                    }
                }
            }
        }

         String queryPointer(PointerPoint ptrPt)
         {
             String details = "";

             switch (ptrPt.PointerDevice.PointerDeviceType)
             {
                 case Windows.Devices.Input.PointerDeviceType.Mouse:
                     details += "\nPointer type: mouse";
                     break;
                 case Windows.Devices.Input.PointerDeviceType.Pen:
                     details += "\nPointer type: pen";
                     if (ptrPt.IsInContact)
                     {
                         details += "\nPressure: " + ptrPt.Properties.Pressure;
                         details += "\nrotation: " + ptrPt.Properties.Orientation;
                         details += "\nTilt X: " + ptrPt.Properties.XTilt;
                         details += "\nTilt Y: " + ptrPt.Properties.YTilt;
                         details += "\nBarrel button pressed: " + ptrPt.Properties.IsBarrelButtonPressed;
                     }
                     break;
                 case Windows.Devices.Input.PointerDeviceType.Touch:
                     details += "\nPointer type: touch";
                     details += "\nrotation: " + ptrPt.Properties.Orientation;
                     details += "\nTilt X: " + ptrPt.Properties.XTilt;
                     details += "\nTilt Y: " + ptrPt.Properties.YTilt;
                     break;
                 default:
                     details += "\nPointer type: n/a";
                     break;
             }

             GeneralTransform gt = Target.TransformToVisual(page);
             Point screenPoint;

             screenPoint = gt.TransformPoint(new Point(ptrPt.Position.X, ptrPt.Position.Y));
             details += "\nPointer Id: " + ptrPt.PointerId.ToString() +
                 "\nPointer location (parent): " + ptrPt.Position.X + ", " + ptrPt.Position.Y +
                 "\nPointer location (screen): " + screenPoint.X + ", " + screenPoint.Y;
             return details;
         }
    }
}


요약 및 다음 단계

이 빠른 시작에서는 C++, C# 또는 Visual Basic으로 작성한 Windows 런타임 앱에서 포인터 입력에 대해 알아보았습니다.

포인터 이벤트는 탭, 밀기, 그리고 보조 마우스 단추, 마우스 휠, 펜 단추 및 펜 지우개를 통한 입력 등의 장치별 조작과 같은 단순한 조작을 관리하는 데 유용합니다.

Windows 8 터치 언어에 설명된 제스처와 같이 좀더 정교한 조작을 처리하려면 빠른 시작: 터치식 입력을 참조하세요.

Windows 8 터치 언어에 대한 자세한 내용은 터치 조작 디자인을 참조하세요.

관련 항목

개발자
사용자 조작에 응답
Windows 스토어 앱 개발(XAML)
빠른 시작: 터치식 입력
디자이너
터치 조작 디자인

 

 

표시:
© 2014 Microsoft