Interações com caneta e Windows Ink em aplicativos do WindowsPen interactions and Windows Ink in Windows apps

Imagem do Hero da caneta da superfície.Hero image of the Surface Pen.
Caneta Surface (disponível para compra na Microsoft Store).Surface Pen (available for purchase at the Microsoft Store).

Visão geralOverview

Otimize seu aplicativo do Windows para entrada de caneta para fornecer a funcionalidade de dispositivo de ponteiro padrão e a melhor experiência de Ink do Windows para seus usuários.Optimize your Windows app for pen input to provide both standard pointer device functionality and the best Windows Ink experience for your users.

Observação

Este tópico se concentra na plataforma Windows Ink.This topic focuses on the Windows Ink platform. Para manipulação de entrada de ponteiro geral (semelhante ao mouse, toque e touchpad), consulte Identificar entrada do ponteiro.For general pointer input handling (similar to mouse, touch, and touchpad), see Handle pointer input.

Usando a tinta em seu aplicativo do WindowsUsing ink in your Windows app

Usar a caneta e o Windows Ink para compilar aplicativos corporativos mais envolventesUse Windows Pen and Ink to build more engaging enterprise apps

A plataforma Windows Ink, juntamente com um dispositivo de caneta, oferece uma maneira natural de criar anotações manuscritas digitais, desenhos e anotações.The Windows Ink platform, together with a pen device, provides a natural way to create digital handwritten notes, drawings, and annotations. A plataforma dá suporte à captura de dados de tinta por entrada de digitalizador, gerenciamento e geração de dados de tinta, renderização desses dados como traços de tinta no dispositivo de saída e conversão de tinta em texto por meio do reconhecimento de manuscrito.The platform supports capturing digitizer input as ink data, generating ink data, managing ink data, rendering ink data as ink strokes on the output device, and converting ink to text through handwriting recognition.

Além de capturar os movimentos e posições básicos da caneta enquanto o usuário escreve ou desenha, seu aplicativo também pode rastrear e coletar os diferentes valores de pressão usados em um traço.In addition to capturing the basic position and movement of the pen as the user writes or draws, your app can also track and collect the varying amounts of pressure used throughout a stroke. Estas informações, juntamente com configurações de formato da ponta da caneta, tamanho, rotação, cor da tinta, rotação e função (tinta simples, apagar, destacar e selecionar) permitem que você ofereça experiências ao usuário que se aproximam do ato de escrever ou desenhar em papel com caneta, lápis ou pincel.This information, along with settings for pen tip shape, size, and rotation, ink color, and purpose (plain ink, erasing, highlighting, and selecting), enables you to provide user experiences that closely resemble writing or drawing on paper with a pen, pencil, or brush.

Observação

Seu aplicativo também pode ser compatível com a entrada à tinta de outros dispositivos baseados em ponteiro, inclusive digitalizadores touch e mouses.Your app can also support ink input from other pointer-based devices, including touch digitizers and mouse devices. 

A plataforma de tinta é muito flexível.The ink platform is very flexible. Ele é projetado para dar suporte a vários níveis de funcionalidade, dependendo dos seus requisitos.It is designed to support various levels of functionality, depending on your requirements.

Para obter diretrizes sobre a experiência do usuário com o Windows Ink, consulte Controles de escrita à tinta.For Windows Ink UX guidelines, see Inking controls.

Componentes da plataforma Windows InkComponents of the Windows Ink platform

ComponenteComponent DescriçãoDescription
InkCanvasInkCanvas Controle da plataforma da interface do usuário XAML que, por padrão, recebe e exibe todas as entradas de uma caneta como um traço de tinta ou um traço para apagar.A XAML UI platform control that, by default, receives and displays all input from a pen as either an ink stroke or an erase stroke.
Para obter mais informações sobre como usar o InkCanvas, consulte Reconhecer traços do Windows Ink como texto e Armazenar e recuperar dados de traço do Windows Ink.For more information about how to use the InkCanvas, see Recognize Windows Ink strokes as text and Store and retrieve Windows Ink stroke data.
InkPresenterInkPresenter Objeto code-behind, instanciado juntamente com um controle InkCanvas (exposto por meio da propriedade InkCanvas.InkPresenter).A code-behind object, instantiated along with an InkCanvas control (exposed through the InkCanvas.InkPresenter property). Esse objeto fornece todas as funcionalidades de escrita à tinta expostas pelo InkCanvas, juntamente com um conjunto que compreende APIs de customização e personalização adicional.This object provides all default inking functionality exposed by the InkCanvas, along with a comprehensive set of APIs for additional customization and personalization.
Para obter mais informações sobre como usar o InkPresenter, consulte Reconhecer traços do Windows Ink como texto e Armazenar e recuperar dados de traço do Windows Ink.For more information about how to use the InkPresenter, see Recognize Windows Ink strokes as text and Store and retrieve Windows Ink stroke data.
InkToolbarInkToolbar O controle da plataforma de IU XAML contendo uma coleção personalizável e extensível de botões que ativam recursos relacionados à tinta em um InkCanvas associado.A XAML UI platform control containing a customizable and extensible collection of buttons that activate ink-related features in an associated InkCanvas.
Para obter mais informações sobre como usar o InkToolbar, consulte Adicionar um InkToolbar a um aplicativo de tinta de aplicativo do Windows.For more information about how to use the InkToolbar, see Add an InkToolbar to a Windows app inking app.
IInkD2DRendererIInkD2DRenderer Permite a renderização de traços de tinta no contexto designado do dispositivo Direct2D de um aplicativo universal do Windows, e não no controle padrão InkCanvas.Enables the rendering of ink strokes onto the designated Direct2D device context of a Universal Windows app, instead of the default InkCanvas control. Isso permite a personalização completa da experiência de escrita à tinta.This enables full customization of the inking experience.
Para obter mais informações, consulte o Exemplo de tinta complexa.For more information, see the Complex ink sample.

Escrita à tinta básica com InkCanvasBasic inking with InkCanvas

Para adicionar funcionalidade básica de escrita à tinta, basta colocar um controle de plataforma UWP InkCanvas na página apropriada do aplicativo.To add basic inking functionality, just place an InkCanvas UWP platform control on the appropriate page in your app.

Por padrão, o InkCanvas dá suporte à entrada de tinta apenas de canetas.By default, the InkCanvas supports ink input only from a pen. A entrada é renderizada como um traço de tinta usando configurações padrão de cor e espessura (uma caneta esferográfica preta com espessura de 2 pixels) ou tratada como um traço de apagar (quando a entrada é da ponta de uma borracha ou da ponta da caneta modificada por um botão de apagar).The input is either rendered as an ink stroke using default settings for color and thickness (a black ballpoint pen with a thickness of 2 pixels), or treated as a stroke eraser (when input is from an eraser tip or the pen tip modified with an erase button).

Observação

Se uma ponta de borracha ou o botão não estiver presente, o InkCanvas poderá ser configurado para processar a entrada da ponta da caneta como um traço para apagar.If an eraser tip or button is not present, the InkCanvas can be configured to process input from the pen tip as an erase stroke.

Neste exemplo, um InkCanvas sobrepõe uma imagem em segundo plano.In this example, an InkCanvas overlays a background image.

Observação

Um InkCanvas tem propriedades de altura e largura padrão de zero, a menos que seja o filho de um elemento que redimensiona automaticamente seus elementos filho, como StackPanel ou controles de grade .An InkCanvas has default Height and Width properties of zero, unless it is the child of an element that automatically sizes its child elements, such as StackPanel or Grid controls.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel x:Name="HeaderPanel" Orientation="Horizontal" Grid.Row="0">
        <TextBlock x:Name="Header"
                   Text="Basic ink sample"
                   Style="{ThemeResource HeaderTextBlockStyle}"
                   Margin="10,0,0,0" />            
    </StackPanel>
    <Grid Grid.Row="1">
        <Image Source="Assets\StoreLogo.png" />
        <InkCanvas x:Name="inkCanvas" />
    </Grid>
</Grid>

Essa série de imagens mostra como entrada de caneta é renderizada por este controle InkCanvas.This series of images shows how pen input is rendered by this InkCanvas control.

Captura de tela do InkCanvas em branco com uma imagem de tela de fundo. Captura de tela do InkCanvas com traços de tinta. Captura de tela do InkCanvas com um traço apagado.
InkCanvas em branco com uma imagem de plano de fundo.The blank InkCanvas with a background image. InkCanvas com traços de tinta.The InkCanvas with ink strokes. O InkCanvas com um traço apagado (observe como apagar funciona em um traço inteiro, não uma parte).The InkCanvas with one stroke erased (note how erase operates on an entire stroke, not a portion).

A funcionalidade de escrita à tinta com suporte do controle InkCanvas é fornecida por um objeto de código-behind chamado InkPresenter.The inking functionality supported by the InkCanvas control is provided by a code-behind object called the InkPresenter.

Para escrita à tinta básica, você não precisa se preocupar com o InkPresenter.For basic inking, you don't have to concern yourself with the InkPresenter. Entretanto, para personalizar e configurar o comportamento de escrita à mão no InkCanvas, você deve acessar o seu objeto correspondente InkPresenter.However, to customize and configure inking behavior on the InkCanvas, you must access its corresponding InkPresenter object.

Personalização básica com InkPresenterBasic customization with InkPresenter

Um objeto InkPresenter é instanciado com cada controle InkCanvas.An InkPresenter object is instantiated with each InkCanvas control.

Observação

O InkPresenter não pode ser instanciado diretamente.The InkPresenter cannot be instantiated directly. Em vez disso, ele é acessado pela propriedade InkPresenter do InkCanvas.Instead, it is accessed through the InkPresenter property of the InkCanvas. 

Além de fornecer todos os comportamentos padrão de escrita à tinta do seu controle InkCanvas correspondente, o InkPresenter fornece um conjunto que compreende APIs para personalização adicional de traços e gerenciamento mais refinado da entrada da tinta (padrão e modificada).Along with providing all default inking behaviors of its corresponding InkCanvas control, the InkPresenter provides a comprehensive set of APIs for additional stroke customization and finer-grained management of the pen input (standard and modified). Isso inclui propriedades de traços, tipos de dispositivos de entrada com suporte e se a entrada é processada pelo objeto ou passada para o app para processamento.This includes stroke properties, supported input device types, and whether input is processed by the object or passed to the app for processing.

Observação

A entrada de tinta padrão (da ponta da caneta ou da borracha/botão) não é modificada com uma funcionalidade de hardware secundária, como um botão de caneta, botão direito do mouse ou mecanismo semelhante.Standard ink input (from either pen tip or eraser tip/button) is not modified with a secondary hardware affordance, such as a pen barrel button, right mouse button, or similar mechanism.

Por padrão, há suporte à tinta somente para entrada de caneta.By default, ink is supported for pen input only. Aqui, configuramos o InkPresenter para interpretar dados de entrada da caneta e do mouse como traços de tinta.Here, we configure the InkPresenter to interpret input data from both pen and mouse as ink strokes. Também definimos alguns atributos iniciais de traço de tinta usados para renderizar traços para o InkCanvas.We also set some initial ink stroke attributes used for rendering strokes to the InkCanvas.

Para habilitar a escrita à tinta por mouse e toque, defina a propriedade InputDeviceTypes do InkPresenter para a combinação de valores CoreInputDeviceTypes que você deseja.To enable mouse and touch inking, set the InputDeviceTypes property of the InkPresenter to the combination of CoreInputDeviceTypes values that you want.

public MainPage()
{
    this.InitializeComponent();

    // Set supported inking device types.
    inkCanvas.InkPresenter.InputDeviceTypes =
        Windows.UI.Core.CoreInputDeviceTypes.Mouse |
        Windows.UI.Core.CoreInputDeviceTypes.Pen;

    // Set initial ink stroke attributes.
    InkDrawingAttributes drawingAttributes = new InkDrawingAttributes();
    drawingAttributes.Color = Windows.UI.Colors.Black;
    drawingAttributes.IgnorePressure = false;
    drawingAttributes.FitToCurve = true;
    inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes);
}

Atributos de traço de tinta podem ser definidos dinamicamente para acomodar as preferências do usuário ou requisitos do aplicativo.Ink stroke attributes can be set dynamically to accommodate user preferences or app requirements.

Aqui, permitimos que um usuário escolha suas preferências em uma lista de cores de tinta.Here, we let a user choose from a list of ink colors.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel x:Name="HeaderPanel" Orientation="Horizontal" Grid.Row="0">
        <TextBlock x:Name="Header"
                   Text="Basic ink customization sample"
                   VerticalAlignment="Center"
                   Style="{ThemeResource HeaderTextBlockStyle}"
                   Margin="10,0,0,0" />
        <TextBlock Text="Color:"
                   Style="{StaticResource SubheaderTextBlockStyle}"
                   VerticalAlignment="Center"
                   Margin="50,0,10,0"/>
        <ComboBox x:Name="PenColor"
                  VerticalAlignment="Center"
                  SelectedIndex="0"
                  SelectionChanged="OnPenColorChanged">
            <ComboBoxItem Content="Black"/>
            <ComboBoxItem Content="Red"/>
        </ComboBox>
    </StackPanel>
    <Grid Grid.Row="1">
        <Image Source="Assets\StoreLogo.png" />
        <InkCanvas x:Name="inkCanvas" />
    </Grid>
</Grid>

Em seguida, manipulamos as alterações feitas na cor selecionada e atualizamos os atributos de traço de tinta de acordo.We then handle changes to the selected color and update the ink stroke attributes accordingly.

// Update ink stroke color for new strokes.
private void OnPenColorChanged(object sender, SelectionChangedEventArgs e)
{
    if (inkCanvas != null)
    {
        InkDrawingAttributes drawingAttributes =
            inkCanvas.InkPresenter.CopyDefaultDrawingAttributes();

        string value = ((ComboBoxItem)PenColor.SelectedItem).Content.ToString();

        switch (value)
        {
            case "Black":
                drawingAttributes.Color = Windows.UI.Colors.Black;
                break;
            case "Red":
                drawingAttributes.Color = Windows.UI.Colors.Red;
                break;
            default:
                drawingAttributes.Color = Windows.UI.Colors.Black;
                break;
        };

        inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes);
    }
}

Estas imagens mostram como a entrada de caneta é processada e personalizada pelo InkPresenter.These images shows how pen input is processed and customized by the InkPresenter.

Captura de tela que mostra o InkCanvas com traços de tinta preta padrão. Captura de tela do InkCanvas com traços de tinta vermelha selecionados pelo usuário.
InkCanvas com traços de tinta preta padrão.The InkCanvas with default black ink strokes. O InkCanvas com traços de tinta vermelha selecionados pelo usuário.The InkCanvas with user selected red ink strokes.  

Para oferecer funcionalidades além de escrever à tinta e apagar, como seleção de traço, seu aplicativo deve identificar entrada específica para o InkPresenter passar por não processado por manipular pelo seu aplicativo.To provide functionality beyond inking and erasing, such as stroke selection, your app must identify specific input for the InkPresenter to pass through unprocessed for handling by your app.

Entrada de passagem para processamento avançadoPass-through input for advanced processing

Por padrão, o InkPresenter processa todas as entradas como um traço de tinta ou de apagar, incluindo entradas modificadas por uma funcionalidade secundária de hardware, como um botão de caneta, um botão direito do mouse ou semelhantes.By default, InkPresenter processes all input as either an ink stroke or an erase stroke, including input modified by a secondary hardware affordance such as a pen barrel button, a right mouse button, or similar. No entanto, os usuários normalmente esperam algumas funcionalidades adicionais ou um comportamento modificado com essas funcionalidades secundárias.However, users typically expect some additional functionality or modified behavior with these secondary affordances.

Em alguns casos, talvez também seja necessário expor a funcionalidade adicional para canetas sem funcionalidades secundárias (funcionalidade geralmente não associada à ponta da caneta), outros tipos de dispositivos de entrada ou algum tipo de comportamento modificado, com base na seleção de um usuário na interface do usuário do seu aplicativo.In some cases, you might also need to expose additional functionality for pens without secondary affordances (functionality not usually associated with the pen tip), other input device types, or some type of modified behavior based on a user selection in your app's UI.

Para dar suporte a isso, o InkPresenter pode ser configurado para deixar uma entrada específica não processada.To support this, InkPresenter can be configured to leave specific input unprocessed. Essa entrada não processada é, então, passada pelo seu aplicativo para processamento.This unprocessed input is then passed through to your app for processing.

Exemplo - Use uma entrada não processada para implementar a seleção de traçoExample - Use unprocessed input to implement stroke selection

A plataforma Windows Ink não fornece suporte interno a ações que exigem entrada modificada, como a seleção de traço.The Windows Ink platform does not provide built-in support for actions that require modified input, such as stroke selection. Para dar suporte a recursos como esse, você deve fornecer uma solução personalizada em seus aplicativos.To support features like this, you must provide a custom solution in your apps.

As seguintes etapas de exemplo de código (todo o código está nos arquivos MainPage.xaml e MainPage.xaml.cs) mostram como habilitar a seleção de traço quando a entrada é modificada com um botão de caneta (ou o botão direito do mouse).The following code example (all code is in the MainPage.xaml and MainPage.xaml.cs files) steps through how to enable stroke selection when input is modified with a pen barrel button (or right mouse button).

  1. Primeiro, definimos a interface do usuário em MainPage.xaml.First, we set up the UI in MainPage.xaml.

    Aqui, adicionados uma tela (abaixo do InkCanvas) para desenhar o traço de seleção.Here, we add a canvas (below the InkCanvas) to draw the selection stroke. Usar uma camada separada para desenhar o traço de seleção deixa o InkCanvas e seu conteúdo intocado.Using a separate layer to draw the selection stroke leaves the InkCanvas and its content untouched.

    Captura de tela do InkCanvas em branco com um Canvas de seleção subjacente.

      <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel x:Name="HeaderPanel" Orientation="Horizontal" Grid.Row="0">
          <TextBlock x:Name="Header"
            Text="Advanced ink customization sample"
            VerticalAlignment="Center"
            Style="{ThemeResource HeaderTextBlockStyle}"
            Margin="10,0,0,0" />
        </StackPanel>
        <Grid Grid.Row="1">
          <!-- Canvas for displaying selection UI. -->
          <Canvas x:Name="selectionCanvas"/>
          <!-- Inking area -->
          <InkCanvas x:Name="inkCanvas"/>
        </Grid>
      </Grid>
    
  2. Em MainPage.xaml.cs, declaramos algumas variáveis globais para manter como referência em aspectos da seleção da IU.In MainPage.xaml.cs, we declare a couple of global variables for keeping references to aspects of the selection UI. Especificamente, a seleção de traço de Laço e o retângulo delimitador que destaca os traços selecionados.Specifically, the selection lasso stroke and the bounding rectangle that highlights the selected strokes.

      // Stroke selection tool.
      private Polyline lasso;
      // Stroke selection area.
      private Rect boundingRect;
    
  3. Em seguida, configuramos o InkPresenter para interpretar dados de entrada tanto da caneta quanto do mouse como traços de tinta, e definimos alguns atributos iniciais de traço de tinta usados para renderizar traços para o InkCanvas.Next, we configure the InkPresenter to interpret input data from both pen and mouse as ink strokes, and set some initial ink stroke attributes used for rendering strokes to the InkCanvas.

    E, o mais importante, usamos a propriedade InputProcessingConfiguration do InkPresenter para indicar que qualquer entrada modificada deve ser processada pelo aplicativo.Most importantly, we use the InputProcessingConfiguration property of the InkPresenter to indicate that any modified input should be processed by the app. A entrada modificada é especificada atribuindo a InputProcessingConfiguration.RightDragAction um valor de InkInputRightDragAction.LeaveUnprocessed.Modified input is specified by assigning InputProcessingConfiguration.RightDragAction a value of InkInputRightDragAction.LeaveUnprocessed. Quando esse valor é definido, o InkPresenter passa para a classe InkUnprocessedInput, um conjunto de eventos de ponteiro para você manipular.When this value is set, the InkPresenter passes through to the InkUnprocessedInput class, a set of pointer events for you to handle.

    Atribuímos ouvintes para os eventos PointerPressed, PointerMoved e PointerReleased não processados passados pelo InkPresenter.We assign listeners for the unprocessed PointerPressed, PointerMoved, and PointerReleased events passed through by the InkPresenter. Todas as funcionalidades de seleção são implementadas nos manipuladores para esses eventos.All selection functionality is implemented in the handlers for these events.

    Por fim, atribuímos ouvintes para os eventos StrokeStarted e StrokesErased do InkPresenter.Finally, we assign listeners for the StrokeStarted and StrokesErased events of the InkPresenter. Usamos os manipuladores para esses limparem a seleção da interface do usuário se um novo traço for iniciado ou um traço existente for apagado.We use the handlers for these events to clean up the selection UI if a new stroke is started or an existing stroke is erased.

    Captura de tela do aplicativo de exemplo de personalização de tinta avanços mostrando o InkCanvas com traços de tinta preta padrão.

      public MainPage()
      {
        this.InitializeComponent();
    
        // Set supported inking device types.
        inkCanvas.InkPresenter.InputDeviceTypes =
          Windows.UI.Core.CoreInputDeviceTypes.Mouse |
          Windows.UI.Core.CoreInputDeviceTypes.Pen;
    
        // Set initial ink stroke attributes.
        InkDrawingAttributes drawingAttributes = new InkDrawingAttributes();
        drawingAttributes.Color = Windows.UI.Colors.Black;
        drawingAttributes.IgnorePressure = false;
        drawingAttributes.FitToCurve = true;
        inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes);
    
        // By default, the InkPresenter processes input modified by
        // a secondary affordance (pen barrel button, right mouse
        // button, or similar) as ink.
        // To pass through modified input to the app for custom processing
        // on the app UI thread instead of the background ink thread, set
        // InputProcessingConfiguration.RightDragAction to LeaveUnprocessed.
        inkCanvas.InkPresenter.InputProcessingConfiguration.RightDragAction =
            InkInputRightDragAction.LeaveUnprocessed;
    
        // Listen for unprocessed pointer events from modified input.
        // The input is used to provide selection functionality.
        inkCanvas.InkPresenter.UnprocessedInput.PointerPressed +=
            UnprocessedInput_PointerPressed;
        inkCanvas.InkPresenter.UnprocessedInput.PointerMoved +=
            UnprocessedInput_PointerMoved;
        inkCanvas.InkPresenter.UnprocessedInput.PointerReleased +=
            UnprocessedInput_PointerReleased;
    
        // Listen for new ink or erase strokes to clean up selection UI.
        inkCanvas.InkPresenter.StrokeInput.StrokeStarted +=
            StrokeInput_StrokeStarted;
        inkCanvas.InkPresenter.StrokesErased +=
            InkPresenter_StrokesErased;
      }
    
  4. Então, definimos manipuladores para os eventos PointerPressed, PointerMoved e PointerReleased não processados passados pelo InkPresenter.We then define handlers for the unprocessed PointerPressed, PointerMoved, and PointerReleased events passed through by the InkPresenter.

    Todas as funcionalidades de seleção são implementadas nesses manipuladores, incluindo o traço de Laço e o retângulo delimitador.All selection functionality is implemented in these handlers, including the lasso stroke and the bounding rectangle.

    Captura de tela do laço de seleção.

      // Handle unprocessed pointer events from modified input.
      // The input is used to provide selection functionality.
      // Selection UI is drawn on a canvas under the InkCanvas.
      private void UnprocessedInput_PointerPressed(
        InkUnprocessedInput sender, PointerEventArgs args)
      {
        // Initialize a selection lasso.
        lasso = new Polyline()
        {
            Stroke = new SolidColorBrush(Windows.UI.Colors.Blue),
            StrokeThickness = 1,
            StrokeDashArray = new DoubleCollection() { 5, 2 },
            };
    
            lasso.Points.Add(args.CurrentPoint.RawPosition);
    
            selectionCanvas.Children.Add(lasso);
        }
    
        private void UnprocessedInput_PointerMoved(
          InkUnprocessedInput sender, PointerEventArgs args)
        {
          // Add a point to the lasso Polyline object.
          lasso.Points.Add(args.CurrentPoint.RawPosition);
        }
    
        private void UnprocessedInput_PointerReleased(
          InkUnprocessedInput sender, PointerEventArgs args)
        {
          // Add the final point to the Polyline object and
          // select strokes within the lasso area.
          // Draw a bounding box on the selection canvas
          // around the selected ink strokes.
          lasso.Points.Add(args.CurrentPoint.RawPosition);
    
          boundingRect =
            inkCanvas.InkPresenter.StrokeContainer.SelectWithPolyLine(
              lasso.Points);
    
          DrawBoundingRect();
        }
    
  5. Para concluir o manipulador de eventos PointerReleased, podemos limpar a camada de seleção de todo o conteúdo (o traço de Laço) e desenhar um retângulo delimitador único ao redor dos traços de tinta circundados pela área de Laço.To conclude the PointerReleased event handler, we clear the selection layer of all content (the lasso stroke) and then draw a single bounding rectangle around the ink strokes encompassed by the lasso area.

    Captura de tela do retângulo delimitador de seleção.

      // Draw a bounding rectangle, on the selection canvas, encompassing
      // all ink strokes within the lasso area.
      private void DrawBoundingRect()
      {
        // Clear all existing content from the selection canvas.
        selectionCanvas.Children.Clear();
    
        // Draw a bounding rectangle only if there are ink strokes
        // within the lasso area.
        if (!((boundingRect.Width == 0) ||
          (boundingRect.Height == 0) ||
          boundingRect.IsEmpty))
          {
            var rectangle = new Rectangle()
            {
              Stroke = new SolidColorBrush(Windows.UI.Colors.Blue),
                StrokeThickness = 1,
                StrokeDashArray = new DoubleCollection() { 5, 2 },
                Width = boundingRect.Width,
                Height = boundingRect.Height
            };
    
            Canvas.SetLeft(rectangle, boundingRect.X);
            Canvas.SetTop(rectangle, boundingRect.Y);
    
            selectionCanvas.Children.Add(rectangle);
          }
        }
    
  6. Por fim, definimos manipuladores para os eventos StrokeStarted e StrokesErased do InkPresenter.Finally, we define handlers for the StrokeStarted and StrokesErased InkPresenter events.

    Esses dois chamam a mesma função de limpeza para limpar a seleção atual sempre que um novo traço é detectado.These both just call the same cleanup function to clear the current selection whenever a new stroke is detected.

      // Handle new ink or erase strokes to clean up selection UI.
      private void StrokeInput_StrokeStarted(
        InkStrokeInput sender, Windows.UI.Core.PointerEventArgs args)
      {
        ClearSelection();
      }
    
      private void InkPresenter_StrokesErased(
        InkPresenter sender, InkStrokesErasedEventArgs args)
      {
        ClearSelection();
      }
    
  7. Consulte a função para remover toda a interface do usuário de seleção da tela de seleção quando um novo traço for iniciado ou um traço existente for apagado.Here's the function to remove all selection UI from the selection canvas when a new stroke is started or an existing stroke is erased.

      // Clean up selection UI.
      private void ClearSelection()
      {
        var strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
        foreach (var stroke in strokes)
        {
          stroke.Selected = false;
        }
        ClearDrawnBoundingRect();
       }
    
      private void ClearDrawnBoundingRect()
      {
        if (selectionCanvas.Children.Any())
        {
          selectionCanvas.Children.Clear();
          boundingRect = Rect.Empty;
        }
      }
    

Renderização de tinta personalizadaCustom ink rendering

Por padrão, a entrada de tinta é processada em um thread de baixa latência em segundo plano e renderizada em andamento ou "molhada" conforme é desenhada.By default, ink input is processed on a low-latency background thread and rendered in-progress, or "wet", as it is drawn. Quando o traço está concluído (caneta ou dedo param de pressionar ou botão do mouse é liberado), o traço é processado do thread de interface do usuário e renderizado como "seco" na camada InkCanvas (acima do conteúdo do aplicativo e substituindo a tinta molhada).When the stroke is completed (pen or finger lifted, or mouse button released), the stroke is processed on the UI thread and rendered "dry" to the InkCanvas layer (above the application content and replacing the wet ink).

Você pode substituir esse comportamento padrão e controlar completamente a experiência de escrita à tinta "secando de forma personalizada" os traços de tinta molhada.You can override this default behavior and completely control the inking experience by "custom drying" the wet ink strokes. Embora o comportamento padrão geralmente seja suficiente para a maioria dos aplicativos, há alguns casos em que a secagem personalizada pode ser necessária, isso inclui:While the default behavior is typically sufficient for most applications, there are a few cases where custom drying might be required, these include:

  • Gerenciamento mais eficiente de coleções grandes ou complexas de traços de tintaMore efficient management of large, or complex, collections of ink strokes
  • Suporte mais eficiente ao movimento panorâmico e ao zoom em telas de tinta grandesMore efficient panning and zooming support on large ink canvases
  • Intercalação da escrita à tinta e de outros objetos, como formas ou texto, mantendo a ordem zInterleaving ink and other objects, such as shapes or text, while maintaining z-order
  • Secagem e conversão de tinta sincronicamente em uma forma DirectX (por exemplo, uma forma ou uma linha reta rasterizada e integrada ao conteúdo do aplicativo, e não a uma camada InkCanvas separada).Drying and converting ink synchronously into a DirectX shape (for example, a straight line or shape rasterized and integrated into application content instead of as a separate InkCanvas layer).

Secar de forma personalizada exige que um objeto IInkD2DRenderer gerencie a entrada de tinta e a renderize para o contexto de dispositivo Direct2D do seu aplicativo Universal do Windows, em vez de o controle padrão InkCanvas.Custom drying requires an IInkD2DRenderer object to manage the ink input and render it to the Direct2D device context of your Universal Windows app, instead of the default InkCanvas control.

Chamar ActivateCustomDrying (antes de o InkCanvas ser carregado) faz com que um aplicativo crie um objeto InkSynchronizer para personalizar como um traço de tinta é renderizado como seco para um SurfaceImageSource ou VirtualSurfaceImageSource.By calling ActivateCustomDrying (before the InkCanvas is loaded), an app creates an InkSynchronizer object to customize how an ink stroke is rendered dry to a SurfaceImageSource or VirtualSurfaceImageSource.

SurfaceImageSource e VirtualSurfaceImageSource fornecem uma superfície compartilhada do DirectX para o seu aplicativo desenhar e compor no seu conteúdo, embora o VSIS forneça uma superfície virtual maior do que a tela para obter movimento panorâmico e zoom eficientes.Both SurfaceImageSource and VirtualSurfaceImageSource provide a DirectX shared surface for your app to draw into and compose into your application's content, although VSIS provides a virtual surface that’s larger than the screen for performant panning and zooming. Como as atualizações visuais dessas superfícies são sincronizadas com o thread de interface do usuário XAML, quando a tinta é renderizada para qualquer uma delas, a tinta molhada pode ser removida do InkCanvas simultaneamente.Because visual updates to these surfaces are synchronized with the XAML UI thread, when ink is rendered to either, the wet ink can be removed from the InkCanvas simultaneously.

Você também pode secar a tinta de forma personalizada para um SwapChainPanel, mas não há garantia de sincronização com o thread de interface do usuário e pode haver um atraso entre o momento em que a tinta é renderizada para o seu SwapChainPanel e o momento em que ela é removida do InkCanvas.You can also custom dry ink to a SwapChainPanel, but synchronization with the UI thread is not guaranteed and there might be a delay between when the ink is rendered to your SwapChainPanel and when ink is removed from the InkCanvas.

Para ver um exemplo completo dessa funcionalidade, consulte Amostra de tinta complexa.For a full example of this functionality, see the Complex ink sample.

Observação

Secagem personalizada e o InkToolbarCustom drying and the InkToolbar
Se o aplicativo substituir o comportamento de renderização da tinta padrão do InkPresenter por uma implementação de secagem personalizada, os traços da tinta renderizada não estarão mais disponíveis para o InkToolbar e os comandos de exclusão internos do InkToolbar não funcionarão conforme esperado.If your app overrides the default ink rendering behavior of the InkPresenter with a custom drying implementation, the rendered ink strokes are no longer available to the InkToolbar and the built-in erase commands of the InkToolbar do not work as expected. Para oferecer uma funcionalidade de exclusão, você deve lidar com todos os eventos de ponteiro, realizar o teste de clique em cada traço e substituir o comando "Apagar toda a tinta" interno.To provide erase functionality, you must handle all pointer events, perform hit-testing on each stroke, and override the built-in "Erase all ink" command.

TópicoTopic DescriçãoDescription
Reconhecer traços de tintaRecognize ink strokes Converta traços de tinta em texto usando o reconhecimento de manuscrito ou em formas usando o reconhecimento personalizado.Convert ink strokes to text using handwriting recognition, or to shapes using custom recognition.
Armazenar e recuperar traços de tintaStore and retrieve ink strokes Armazene dados de traço de tinta em um arquivo Graphics Interchange Format (GIF) usando metadados incorporados Ink Serialized Format (ISF).Store ink stroke data in a Graphics Interchange Format (GIF) file using embedded Ink Serialized Format (ISF) metadata.
Adicionar um InkToolbar a um aplicativo de tinta do WindowsAdd an InkToolbar to a Windows inking app Adicione um InkToolbar padrão a um aplicativo de escrita à tinta de aplicativo do Windows, adicione um botão de caneta personalizado ao InkToolbar e associe o botão de caneta personalizada a uma definição de caneta personalizada.Add a default InkToolbar to a Windows app inking app, add a custom pen button to the InkToolbar, and bind the custom pen button to a custom pen definition.

APIsAPIs

ExemplosSamples

Exemplos de arquivo mortoArchive Samples