Interacciones de lápiz y Windows Ink en aplicaciones de WindowsPen interactions and Windows Ink in Windows apps

Imagen de Hero del lápiz de Surface.Hero image of the Surface Pen.
Lápiz para Surface (disponible para su compra en Microsoft Store).Surface Pen (available for purchase at the Microsoft Store).

Información generalOverview

Optimice su aplicación de Windows para que la entrada manuscrita proporcione la funcionalidad de dispositivo de puntero estándar y la mejor experiencia de Windows Ink para los usuarios.Optimize your Windows app for pen input to provide both standard pointer device functionality and the best Windows Ink experience for your users.

Nota

Este tema se centra en la plataforma Windows Ink.This topic focuses on the Windows Ink platform. Para poder controlar las entradas generales del puntero (es algo similar al mouse, a la función táctil y al panel táctil), consulta el artículo Controlar la entrada de puntero.For general pointer input handling (similar to mouse, touch, and touchpad), see Handle pointer input.

Uso de entradas manuscritas en la aplicación de WindowsUsing ink in your Windows app

Uso del lápiz de Windows y Windows Ink para crear aplicaciones empresariales más atractivasUse Windows Pen and Ink to build more engaging enterprise apps

La plataforma de Windows Ink, junto con un dispositivo de lápiz, te ofrece una forma natural de crear notas, dibujos y anotaciones manuscritas, todo ello de forma digital.The Windows Ink platform, together with a pen device, provides a natural way to create digital handwritten notes, drawings, and annotations. Asimismo, la plataforma te permite capturar los datos de entrada del digitalizador a modo de datos de entrada de lápiz, generar datos de entrada de lápiz, administrarlos, representarlos como trazos de lápiz en el dispositivo de salida y convertirlos en texto a través del reconocimiento de escritura a mano.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.

Además de capturar la posición básica y el movimiento del lápiz a medida que el usuario escribe o dibuja, la aplicación también puede realizar un seguimiento y recopilar los distintos niveles de presión que se usan en un trazo.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. Esta información, junto con la configuración de la forma de la punta del lápiz, el tamaño y la rotación, el color de la entrada de lápiz y el propósito (como la entrada de lápiz sin formato y las acciones de borrar, resaltar y seleccionar), te permite proporcionar experiencias de usuario que se asemejan mucho a escribir o dibujar sobre papel con un lápiz, un bolígrafo o un 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.

Nota

La aplicación también es compatible con la entrada de lápiz de otros dispositivos señaladores, como digitalizadores táctiles y dispositivos de mouse.Your app can also support ink input from other pointer-based devices, including touch digitizers and mouse devices. 

La plataforma de entrada de lápiz es muy flexible.The ink platform is very flexible. Está diseñada para admitir varios niveles de funcionalidad, dependiendo de los requisitos.It is designed to support various levels of functionality, depending on your requirements.

Para obtener directrices sobre la experiencia del usuario de Windows Ink, consulta Controles de entrada de lápiz.For Windows Ink UX guidelines, see Inking controls.

Componentes de la plataforma Windows InkComponents of the Windows Ink platform

ComponenteComponent DescripciónDescription
InkCanvasInkCanvas Un control de plataforma de interfaz de usuario XAML que, de manera predeterminada, recibe y muestra todas las entradas de lápiz como un trazo de lápiz o un trazo de borrado.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 obtener más información sobre cómo usar InkCanvas, consulta Reconocer trazos de Windows Ink como texto y Almacenar y recuperar datos de trazos de lápiz de 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.
ObjetoInkPresenter Un objeto de código subyacente, cuya instancia se creó con un control InkCanvas (expuesto a través de la propiedad InkCanvas.InkPresenter).A code-behind object, instantiated along with an InkCanvas control (exposed through the InkCanvas.InkPresenter property). Este objeto proporciona todas las funcionalidades de entrada manuscrita predeterminadas y que expuso InkCanvas, junto con un completo conjunto de API para la personalización 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 obtener más información sobre cómo usar InkPresenter, consulta Reconocer trazos de Windows Ink como texto y Almacenar y recuperar datos de trazos de lápiz de 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 Control de plataforma de interfaz de usuario XAML que contiene una colección personalizable y extensible de botones que activan las características relacionadas con la tinta en un InkCanvasasociado.A XAML UI platform control containing a customizable and extensible collection of buttons that activate ink-related features in an associated InkCanvas.
Para obtener más información sobre cómo usar el control InkToolbar, vea Agregar un control inktoolbar a una aplicación de entrada de lápiz de la aplicación Windows.For more information about how to use the InkToolbar, see Add an InkToolbar to a Windows app inking app.
IInkD2DRendererIInkD2DRenderer Habilita la representación de trazos de lápiz en el contexto de dispositivo de Direct2D designado de una aplicación universal de Windows, en lugar del control InkCanvas predeterminado.Enables the rendering of ink strokes onto the designated Direct2D device context of a Universal Windows app, instead of the default InkCanvas control. Esto permite la personalización completa de la experiencia de entrada manuscrita.This enables full customization of the inking experience.
Para obtener más información, consulta Complex ink sample (Muestra de entrada de lápiz compleja).For more information, see the Complex ink sample.

Entrada manuscrita básica con InkCanvasBasic inking with InkCanvas

Para agregar la funcionalidad básica de entrada manuscrita, solo tiene que colocar un control de plataforma de UWP de InkCanvas en la página correspondiente de la aplicación.To add basic inking functionality, just place an InkCanvas UWP platform control on the appropriate page in your app.

De manera predeterminada, el control InkCanvas solo admite la entrada de lápiz que se haya realizado con un lápiz.By default, the InkCanvas supports ink input only from a pen. La entrada se representa como un trazo de lápiz mediante la configuración predeterminada de color y espesor (como un bolígrafo negro con un grosor de 2 píxeles) o se trata como si fuera un borrador de trazos (cuando la entrada se realiza desde un extremo del borrador o cuando la punta del lápiz se modifica con un botón de borrador).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).

Nota

Si no hay ningún botón o extremo borrador, InkCanvas puede configurarse para procesar la entrada de la punta del lápiz como trazos de borrado.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.

En este ejemplo, un control InkCanvas se superpone a una imagen en segundo plano.In this example, an InkCanvas overlays a background image.

Nota

Un control InkCanvas tiene las propiedades height y width predeterminadas de cero, a menos que sea el elemento secundario de un elemento que ajusta automáticamente el tamaño de sus elementos secundarios, como los controles StackPanel o Grid .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>

Esta serie de imágenes muestra cómo se representa la entrada manuscrita mediante el control InkCanvas.This series of images shows how pen input is rendered by this InkCanvas control.

Captura de pantalla del InkCanvas en blanco con una imagen de fondo. Captura de pantalla del InkCanvas con trazos de lápiz. Captura de pantalla del InkCanvas con un trazo borrado.
El InkCanvas en blanco con una imagen de fondo.The blank InkCanvas with a background image. InkCanvas con trazos de lápiz.The InkCanvas with ink strokes. Control InkCanvas con un trazo borrado (ten en cuenta que la opción de borrado actúa en todo el trazo, no en una parte).The InkCanvas with one stroke erased (note how erase operates on an entire stroke, not a portion).

La funcionalidad de entrada manuscrita admitida por el control InkCanvas la proporciona un objeto de código subyacente denominado InkPresenter.The inking functionality supported by the InkCanvas control is provided by a code-behind object called the InkPresenter.

Para realizar entradas manuscritas básicas, no es necesario preocuparse por InkPresenter.For basic inking, you don't have to concern yourself with the InkPresenter. Sin embargo, para personalizar y configurar el comportamiento de la entrada manuscrita en la clase InkCanvas, debe acceder al objeto correspondiente InkPresenter.However, to customize and configure inking behavior on the InkCanvas, you must access its corresponding InkPresenter object.

Personalización básica con InkPresenterBasic customization with InkPresenter

Se crea una instancia de un objeto InkPresenter con cada control InkCanvas.An InkPresenter object is instantiated with each InkCanvas control.

Nota

No se pueden crear instancias de la propiedad InkPresenter directamente.The InkPresenter cannot be instantiated directly. En su lugar, debes acceder a ellas a través de la propiedad InkPresenter de la clase InkCanvas.Instead, it is accessed through the InkPresenter property of the InkCanvas. 

Además de proporcionar todos los comportamientos predeterminados de entrada de lápiz de su control InkCanvas correspondiente, el objeto InkPresenter proporciona un conjunto completo de API para la personalización de trazos adicionales y la administración más específica de la entrada manuscrita (estándar y modificado).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). Esto incluye las propiedades de trazo, los tipos de dispositivo de entrada admitidos y si el objeto procesa la entrada o se pasa a la aplicación para su procesamiento.This includes stroke properties, supported input device types, and whether input is processed by the object or passed to the app for processing.

Nota

La entrada manuscrita estándar (desde la punta del lápiz o el botón o la punta del borrador) no se modifica con una prestación de hardware secundaria, como un botón de barril del lápiz, un botón secundario del mouse o un mecanismo similar.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.

De forma predeterminada, la tinta solo se admite para la entrada manuscrita.By default, ink is supported for pen input only. En este apartado, configuraremos InkPresenter para que interprete los datos de entrada del lápiz y el mouse como trazos de lápiz.Here, we configure the InkPresenter to interpret input data from both pen and mouse as ink strokes. También establecemos algunos atributos de trazo de lápiz iniciales que se usan para representar trazos en el InkCanvas.We also set some initial ink stroke attributes used for rendering strokes to the InkCanvas.

Para habilitar el mouse y la entrada táctil, establezca la propiedad InputDeviceTypes del objeto InkPresenter en la combinación de los valores de CoreInputDeviceTypes que desee.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);
}

Los atributos de trazo de lápiz se pueden establecer de forma dinámica para así ajustarlos a las preferencias del usuario o a los requisitos de la aplicación.Ink stroke attributes can be set dynamically to accommodate user preferences or app requirements.

Aquí dejamos que un usuario elija en una lista de colores de entrada de lápiz.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>

A continuación, controlamos los cambios en el color seleccionado y actualizamos los atributos de trazo de lápiz en consecuencia.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 imágenes muestran cómo se procesa y personaliza la entrada manuscrita mediante InkPresenter.These images shows how pen input is processed and customized by the InkPresenter.

Captura de pantalla que muestra el InkCanvas con trazos de lápiz negros predeterminados. Captura de pantalla de InkCanvas con trazos de tinta roja seleccionados por el usuario.
InkCanvas con trazos de lápiz negros predeterminados.The InkCanvas with default black ink strokes. InkCanvas con trazos de tinta roja seleccionados por el usuario.The InkCanvas with user selected red ink strokes.  

Para proporcionar funcionalidades que vayan más allá de la entrada manuscrita y el borrado (como la selección de trazo), la aplicación debe identificar la entrada específica de InkPresenter, la cual debe pasarse sin procesar para que la aplicación la controle.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 paso a través para el procesamiento avanzadoPass-through input for advanced processing

De forma predeterminada, InkPresenter procesa toda la entrada como un trazo de tinta o un trazo de borrado, incluida la entrada modificada por una prestación de hardware secundaria, como un botón de barril del lápiz, un botón secundario del mouse o similar.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. Sin embargo, los usuarios normalmente esperan alguna funcionalidad adicional o un comportamiento modificado con estas prestaciones secundarias.However, users typically expect some additional functionality or modified behavior with these secondary affordances.

En algunos casos, es posible que también necesite exponer funcionalidad adicional para los lápices sin prestaciones secundarias (funcionalidad que normalmente no está asociada a la punta del lápiz), otros tipos de dispositivos de entrada o algún tipo de comportamiento modificado basado en una selección de usuario en la interfaz de usuario de la aplicación.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 que esta acción sea compatible, puedes configurar InkPresenter para que deje una entrada específica sin procesar.To support this, InkPresenter can be configured to leave specific input unprocessed. A continuación, esta entrada sin procesar se pasa a través de la aplicación para su procesamiento.This unprocessed input is then passed through to your app for processing.

Ejemplo: uso de la entrada no procesada para implementar la selección de trazosExample - Use unprocessed input to implement stroke selection

La plataforma de tinta de Windows no proporciona compatibilidad integrada para acciones que requieren una entrada modificada, como la selección de trazo.The Windows Ink platform does not provide built-in support for actions that require modified input, such as stroke selection. Para admitir características como esta, debe proporcionar una solución personalizada en sus aplicaciones.To support features like this, you must provide a custom solution in your apps.

En el ejemplo de código siguiente (todo el código está en los archivos MainPage. XAML y MainPage.xaml.cs), se explica cómo habilitar la selección de trazos cuando la entrada se modifica con un botón de barril del lápiz (o el botón secundario del 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. En primer lugar, debemos configurar la interfaz de usuario en MainPage.xaml.First, we set up the UI in MainPage.xaml.

    Una vez hecho esto, agregamos un lienzo (debajo de InkCanvas) para dibujar el trazo de selección.Here, we add a canvas (below the InkCanvas) to draw the selection stroke. Si usas una capa independiente para dibujar el trazo de selección, InkCanvas y su contenido no se modifican.Using a separate layer to draw the selection stroke leaves the InkCanvas and its content untouched.

    Captura de pantalla del InkCanvas en blanco con un lienzo de selección subyacente.

      <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. En MainPage.xaml.cs, declaramos un par de variables globales para mantener las referencias a los aspectos de la interfaz de usuario de selección.In MainPage.xaml.cs, we declare a couple of global variables for keeping references to aspects of the selection UI. Usaremos específicamente el trazo de lazo de selección y el rectángulo delimitador que resalta los trazos seleccionados.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. A continuación, configuraremos el objeto InkPresenter para interpretar los datos de entrada del lápiz y del mouse como trazos de entrada de lápiz, y para establecer algunos atributos de trazo de lápiz iniciales que se usan para representar trazos en el 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.

    Recuerda usar la propiedad InputProcessingConfiguration de InkPresenter para indicar que la aplicación debe procesar cualquier entrada modificada.Most importantly, we use the InputProcessingConfiguration property of the InkPresenter to indicate that any modified input should be processed by the app. La entrada modificada se especifica asignando InputProcessingConfiguration. RightDragAction a InkInputRightDragAction. LeaveUnprocessed.Modified input is specified by assigning InputProcessingConfiguration.RightDragAction a value of InkInputRightDragAction.LeaveUnprocessed. Cuando se establece este valor, el objeto InkPresenter pasa a la clase InkUnprocessedInput , un conjunto de eventos de puntero para que los controle.When this value is set, the InkPresenter passes through to the InkUnprocessedInput class, a set of pointer events for you to handle.

    Asignamos agentes de escucha para los eventos PointerPressed, PointerMovedy PointerReleased sin procesar que ha pasado el objeto InkPresenter.We assign listeners for the unprocessed PointerPressed, PointerMoved, and PointerReleased events passed through by the InkPresenter. Todas las funcionalidades de selección se implementan en los controladores de estos eventos.All selection functionality is implemented in the handlers for these events.

    Por último, asignamos agentes de escucha para los eventos StrokeStarted y StrokesErased de la propiedad InkPresenter.Finally, we assign listeners for the StrokeStarted and StrokesErased events of the InkPresenter. Los controladores de estos eventos se usan para limpiar la interfaz de usuario de selección si se inicia un nuevo trazo o se borra un trazo existente.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 pantalla de la aplicación de ejemplo de personalización de entradas manuscritas que muestra el InkCanvas con trazos de lápiz negros predeterminados.

      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. A continuación, se definen Controladores para los eventos PointerPressed, PointerMovedy PointerReleased sin procesar que ha pasado el objeto InkPresenter.We then define handlers for the unprocessed PointerPressed, PointerMoved, and PointerReleased events passed through by the InkPresenter.

    Todas las funcionalidades de selección se implementan en estos controladores, incluido el trazo de lazo y el rectángulo delimitador.All selection functionality is implemented in these handlers, including the lasso stroke and the bounding rectangle.

    Captura de pantalla del lazo de selección.

      // 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 el controlador de eventos PointerReleased, borramos la capa de selección de todo el contenido (trazo de lazo) y, a continuación, dibujamos un único rectángulo delimitador alrededor de los trazos de lápiz incluidos en el área del lazo.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 pantalla del rectángulo delimitador de selección.

      // 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 último, definimos los controladores de los eventos StrokeStarted y StrokesErased de la propiedad InkPresenter.Finally, we define handlers for the StrokeStarted and StrokesErased InkPresenter events.

    Ambos llaman a la misma función de limpieza para borrar la selección actual siempre que se detecta un nuevo trazo.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. Esta es la función para quitar toda la interfaz de usuario de selección del lienzo de selección cuando se inicia un nuevo trazo o se borra un trazo existente.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;
        }
      }
    

Representación de entrada de lápiz personalizadaCustom ink rendering

De forma predeterminada, la entrada de lápiz se procesa en un subproceso en segundo plano de latencia baja y se representa en curso, o "húmeda", cuando se dibuja.By default, ink input is processed on a low-latency background thread and rendered in-progress, or "wet", as it is drawn. Cuando se completa el trazo (se levanta el lápiz o el dedo o se libera el botón del mouse), el trazo se procesa en el subproceso de la interfaz de usuario y se representa como "seco" en la capa de InkCanvas (lo verás sobre el contenido de la aplicación y reemplazando la entrada de lápiz húmeda).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).

Puede invalidar este comportamiento predeterminado y controlar por completo la experiencia de entrada manuscrita mediante el "secado personalizado" de los trazos de la tinta húmeda.You can override this default behavior and completely control the inking experience by "custom drying" the wet ink strokes. Aunque el comportamiento predeterminado suele ser suficiente para la mayoría de las aplicaciones, hay algunos casos en los que es posible que se requiera un secado personalizado, entre los que se incluyen:While the default behavior is typically sufficient for most applications, there are a few cases where custom drying might be required, these include:

  • Administración más eficaz de colecciones grandes o complejas de trazos de tintaMore efficient management of large, or complex, collections of ink strokes
  • Compatibilidad más eficaz de movimiento panorámico y zoom en lienzos de tinta grandesMore efficient panning and zooming support on large ink canvases
  • Intercalar la entrada de lápiz y otros objetos, como formas o texto, manteniendo el orden zInterleaving ink and other objects, such as shapes or text, while maintaining z-order
  • Secado y conversión de la entrada de lápiz sincrónicamente en una forma de DirectX (por ejemplo, una línea o forma recta rasterizada e integrada en el contenido de la aplicación en lugar de como una capa de InkCanvas independiente).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).

El secado personalizado requiere un objeto IInkD2DRenderer para administrar la entrada de lápiz y representarla en el contexto de dispositivo Direct2D de la aplicación universal de Windows, en lugar del control InkCanvas predeterminado.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.

Al llamar a ActivateCustomDrying (antes de cargar InkCanvas), una aplicación crea un objeto InkSynchronizer para personalizar la representación de un trazo de lápiz seco en la clase SurfaceImageSource o 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.

Los objetos SurfaceImageSource y VirtualSurfaceImageSource proporcionan una superficie compartida de DirectX para que la aplicación se dibuje en el contenido de la aplicación y se componga en él, aunque VSI proporciona una superficie virtual más grande que la pantalla para la panorámica y el aumento del rendimiento.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. Dado que las actualizaciones visuales de estas superficies se sincronizan con el subproceso de la interfaz de usuario de XAML, cuando la entrada de lápiz se representa en cualquiera de ellos, la tinta húmeda se puede quitar del InkCanvas simultáneamente.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.

También puede personalizar la tinta seca para un SwapChainPanel, pero no se garantiza la sincronización con el subproceso de la interfaz de usuario y puede haber un retraso entre el momento en que se representa la tinta en el swapchainpanel y el momento en que se quita la tinta del 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 obtener un ejemplo completo de esta funcionalidad, consulta la muestra de entrada de lápiz compleja.For a full example of this functionality, see the Complex ink sample.

Nota

El secado personalizado y la clase InkToolbarCustom drying and the InkToolbar
Si tu aplicación invalida el comportamiento predeterminado de representación de entrada de lápiz de la clase InkPresenter con una implementación de secado personalizado, los trazos de lápiz representados ya no están disponibles para InkToolbar y los comandos de borrado integrados de InkToolbar no funcionan según lo previsto.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 proporcionar la funcionalidad de borrado, debes controlar todos los eventos de puntero, realizar la prueba de posicionamiento en cada trazo e invalidar el comando "Borrar todas las entradas de lápiz" integrado.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.

TemaTopic DescripciónDescription
Reconocer trazos de lápizRecognize ink strokes Conversión de trazos de lápiz en texto mediante el reconocimiento de escritura a mano o en formas mediante el reconocimiento personalizadoConvert ink strokes to text using handwriting recognition, or to shapes using custom recognition.
Almacenar y recuperar trazos de lápizStore and retrieve ink strokes Almacena los datos de trazo de lápiz en un archivo de formato de intercambio de elementos gráficos (GIF) mediante los metadatos Ink Serialized Format (ISF) insertados.Store ink stroke data in a Graphics Interchange Format (GIF) file using embedded Ink Serialized Format (ISF) metadata.
Agregar un control InkToolbar a una aplicación de entrada manuscrita de WindowsAdd an InkToolbar to a Windows inking app Agregue un control InkToolbar predeterminado a una aplicación de entrada manuscrita de la aplicación de Windows, agregue un botón de lápiz personalizado al control InkToolbar y enlace el botón del lápiz personalizado a una definición de lápiz 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.

API existentesAPIs

EjemplosSamples

Muestras de archivoArchive Samples