Compartir a través de


Interacciones de lápiz y Windows Ink en aplicaciones de Windows

imagen destacada del Lápiz Surface.
Surface Pen (disponible para compra en Microsoft Store).

Información general

Optimice la aplicación de Windows para la entrada de lápiz para proporcionar la funcionalidad estándar de dispositivo de puntero y la mejor experiencia de Windows Ink para los usuarios.

Nota:

Este tema se centra en la plataforma de Windows Ink. Para la gestión general de entrada de puntero (similar al mouse, la entrada táctil y el touchpad), consulte Gestión de entrada de puntero.

Usar tinta digital en tu aplicación de Windows

Usar Windows Pen and Ink para crear aplicaciones empresariales más atractivas

La plataforma Windows Ink, junto con un dispositivo de lápiz, proporciona una manera natural de crear notas manuscritas digitales, dibujos y anotaciones. La plataforma admite la captura de entrada del digitalizador como datos de entrada de lápiz, la generación de datos de entrada de lápiz, la administración de datos de entrada de lápiz, la representación de datos de lápiz como trazos de lápiz en el dispositivo de salida y la conversión de entrada de lápiz en texto mediante el reconocimiento de escritura a mano.

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 las distintas cantidades de presión usadas a lo largo de un trazo. 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 lápiz y el propósito (tinta simple, borrado, resaltado y selección), le permite proporcionar experiencias de usuario que se parezcan mucho a escribir o dibujar en papel con un lápiz, lápiz o pincel.

Nota:

La aplicación también puede admitir la entrada de lápiz desde otros dispositivos basados en punteros, incluidos digitalizadores táctiles y dispositivos de ratón. 

La plataforma de tinta es muy flexible. Está diseñado para admitir varios niveles de funcionalidad, en función de sus requisitos.

Para obtener las directrices sobre la experiencia de usuario de Windows Ink, consulte controles de escritura.

Componentes de la plataforma Windows Ink

Componente Descripción
InkCanvas Un control de plataforma de interfaz de usuario XAML que, de forma predeterminada, recibe y muestra toda la entrada de un lápiz como un trazo de tinta o un trazo de borrado.
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 trazo de Windows Ink.
PresentadorDeTinta Objeto de código subyacente, que se instancia junto con un control InkCanvas (expuesto mediante la propiedad InkCanvas.InkPresenter). Este objeto proporciona toda la funcionalidad de entrada manuscrita predeterminada expuesta por el InkCanvas, junto con un conjunto completo de APIs para personalización adicional.
Para obtener más información sobre cómo usar InkPresenter, consulta Reconocer trazos de Windows Ink como texto y Almacenar y recuperar los datos de trazos de Windows Ink.
Barra de herramientas de tinta Control de interfaz de usuario XAML que contiene una colección personalizable y extensible de botones que activan características relacionadas con la tinta en una InkCanvas asociada .
Para obtener más información sobre cómo usar InkToolbar, consulte Agregar InkToolbar a una aplicación de Windows para inking.
IInkD2DRenderer Habilita la representación de trazos de lápiz en el contexto designado del dispositivo Direct2D de una aplicación universal de Windows, en lugar del control InkCanvas predeterminado. Esto permite la personalización completa de la experiencia de entintado.
Para obtener más información, consulte la muestra de tinta del complejo .

Entintado básico con InkCanvas

Para agregar funcionalidad básica de entrada manuscrita, basta con colocar un control de la plataforma UWP InkCanvas en la página adecuada de su aplicación.

De forma predeterminada, InkCanvas solo admite la entrada de lápiz desde un lápiz. La entrada se representa como un trazo de tinta usando la configuración predeterminada para el color y el grosor (un bolígrafo negro con un grosor de 2 píxeles) o se trata como un borrador de trazo (cuando la entrada procede de una punta de borrador o la punta del bolígrafo modificada con un botón de borrado).

Nota:

Si no hay un borrador de punta o botón, el InkCanvas se puede configurar para procesar la entrada desde la punta del lápiz como una acción de borrado.

En este ejemplo, un InkCanvas superpone una imagen de fondo.

Nota:

Un InkCanvas tiene propiedades predeterminadas Height y Width de cero, a menos que sea el elemento secundario de un elemento que dimensione automáticamente a sus elementos secundarios, como StackPanel o Grid.

<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 del lápiz mediante este control InkCanvas .

Captura de pantalla de InkCanvas en blanco con una imagen de fondo. Captura de pantalla de InkCanvas con trazos de lápiz. Captura de pantalla de InkCanvas con un trazo borrado.
El InkCanvas en blanco con una imagen de fondo. El InkCanvas con trazos de lápiz. El InkCanvas borrado con un solo trazo (observe cómo el borrado afecta a un trazo entero y no a una parte).

La funcionalidad de entrada manuscrita admitida por el control InkCanvas se proporciona mediante un objeto de código subyacente denominado InkPresenter.

Para el entintado básico, no tiene que preocuparse por el InkPresenter. Sin embargo, para personalizar y configurar el comportamiento de entrada manuscrita en el InkCanvas, debe acceder a su objeto InkPresenter correspondiente.

Personalización básica con InkPresenter

Se crea una instancia de un objeto InkPresenter con cada control InkCanvas.

Nota:

El InkPresenter no se puede instanciar directamente. En su lugar, se accede a él a través de la propiedad InkPresenter del InkCanvas

Además de ofrecer todos los comportamientos estándar de escritura a mano de su control InkCanvas, el InkPresenter proporciona un conjunto completo de APIs para la personalización adicional de los trazos y la gestión más detallada de la entrada del lápiz óptico (tanto estándar como modificada). 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.

Nota:

La entrada de lápiz estándar (desde la punta del lápiz o la punta del borrador o el botón) no se modifica con una prestación de hardware secundaria, como un botón de barril de lápiz, un botón derecho del mouse o un mecanismo similar.

De forma predeterminada, la tinta solo se admite para la entrada de lápiz. Aquí, configuramos InkPresenter para interpretar los datos de entrada del lápiz y el mouse como trazos de lápiz. También se establecen algunos atributos iniciales de trazos de lápiz usados para representar trazos en el InkCanvas.

Para habilitar el mouse y la tinta táctil, configure la propiedad InputDeviceTypes del InkPresenter a la combinación de los valores de CoreInputDeviceTypes que prefiera.

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 trazos de lápiz se pueden establecer dinámicamente para dar cabida a las preferencias del usuario o a los requisitos de la aplicación.

Aquí, se permite que un usuario elija entre una lista de colores de tinta.

<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, se controlan los cambios en el color seleccionado y se actualizan los atributos de trazos de lápiz en consecuencia.

// 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 la entrada del lápiz se procesa y personaliza mediante InkPresenter.

Captura de pantalla que muestra InkCanvas con trazos de lápiz negro predeterminados.

El InkCanvas con trazos predeterminados de tinta negra.

Captura de pantalla de InkCanvas con trazos de lápiz rojos seleccionados por el usuario.

El InkCanvas con trazos de lápiz rojos seleccionados por el usuario.

Para ofrecer funcionalidades adicionales a la de escribir y borrar, como la selección de trazos, su aplicación debe identificar entradas específicas que el InkPresenter debe dejar pasar sin procesar, para que sean gestionadas por su aplicación.

Entrada directa para el procesamiento avanzado

De forma predeterminada, InkPresenter procesa toda la entrada como un trazo de lápiz o un trazo de borrado, incluida la entrada modificada por una prestación de hardware secundaria, como un botón de barril de lápiz, un botón derecho del mouse o similar. Sin embargo, los usuarios suelen esperar alguna funcionalidad adicional o un comportamiento modificado con estas prestaciones secundarias.

En algunos casos, es posible que también tengas que exponer funcionalidades adicionales para lápices sin funciones secundarias (funcionalidad no normalmente asociada con la punta del lápiz), otros tipos de dispositivos de entrada o algún tipo de conducta modificada en función de una opción del usuario en la interfaz de la aplicación.

Para admitir esto, InkPresenter se puede configurar para dejar sin procesar una entrada específica. Esta entrada sin procesar se pasa a la aplicación para su procesamiento.

Ejemplo: Uso de la entrada sin procesar para implementar la selección de trazo

La plataforma Windows Ink no proporciona compatibilidad integrada con acciones que requieren entrada modificada, como la selección de trazo. Para admitir características como esta, debe proporcionar una solución personalizada en las aplicaciones.

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 trazo cuando se modifica la entrada con un botón de lápiz (o botón derecho del mouse).

  1. En primer lugar, configuramos la interfaz de usuario en MainPage.xaml.

    Aquí, agregamos un lienzo (debajo del InkCanvas) para dibujar el trazo de selección. El uso de una capa independiente para dibujar el trazo de selección deja el InkCanvas y su contenido sin modificar.

    Captura de pantalla del

      <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 referencias a aspectos de la interfaz de usuario de selección. En concreto, el trazo de lazo de selección y el rectángulo delimitador que resalta los trazos seleccionados.

      // Stroke selection tool.
      private Polyline lasso;
      // Stroke selection area.
      private Rect boundingRect;
    
  3. A continuación, configuramos el InkPresenter para interpretar los datos de entrada del lápiz y el mouse como trazos de lápiz y establecer algunos atributos iniciales de trazos de lápiz usados para representar trazos en el InkCanvas.

    Lo más importante es que usamos la propiedad InputProcessingConfiguration de InkPresenter para indicar que la aplicación debe procesar cualquier entrada modificada. La entrada modificada se especifica asignando InputProcessingConfiguration.RightDragAction un valor de InkInputRightDragAction.LeaveUnprocessed. Cuando se establece este valor, el InkPresenter pasa a la clase InkUnprocessedInput, un conjunto de eventos de puntero que se van a controlar.

    Asignamos agentes de escucha para los eventos PointerPressed, PointerMovedy PointerReleased pasados por el InkPresenter. Toda la funcionalidad de selección se implementa en los controladores para estos eventos.

    Por último, asignamos agentes de escucha para los eventos de StrokeStarted y StrokesErased de la InkPresenter. Usamos los controladores de estos eventos para limpiar la interfaz de usuario de selección si se inicia un nuevo trazo o se borra un trazo existente.

    Captura de pantalla de la aplicación de ejemplo de personalización avanzada de tinta que muestra el lienzo de tinta con trazos de tinta negra 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, definimos controladores para los eventos pointerPressed pointerPressed, PointerMovedy PointerReleased pasados por el InkPresenter.

    Toda la funcionalidad de selección se implementa en estos controladores, incluyendo el trazo de lazo y el rectángulo delimitador.

    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, limpiamos la capa de selección de todo el contenido (los trazos del lazo) y, a continuación, dibujamos un único rectángulo delimitador alrededor de los trazos de tinta que abarca el área de lazo.

    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 controladores para los eventos StrokeStarted y StrokesErased InkPresenter.

    Ambos simplemente llaman a la misma función de limpieza para borrar la selección actual cada vez que se detecta un nuevo trazo.

      // 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.

      // 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 tinta personalizada

De forma predeterminada, la entrada de lápiz se procesa en un subproceso de fondo de baja latencia y se representa mientras se dibuja, o "mojado". Cuando se completa el trazo (cuando se levanta el lápiz, el dedo o se suelta el botón del ratón), el trazo se procesa en el subproceso de la interfaz de usuario y se representa como "seco" en la capa de InkCanvas (por encima del contenido de la aplicación y reemplazando la tinta húmeda).

Puede invalidar este comportamiento predeterminado y controlar completamente la experiencia de escritura mediante el "secado personalizado" de los trazos de tinta húmedos. Aunque el comportamiento predeterminado suele ser suficiente para la mayoría de las aplicaciones, hay algunos casos en los que podría ser necesario el secado personalizado, estos incluyen:

  • Administración más eficaz de colecciones de trazos de lápiz grandes o complejos
  • Compatibilidad con panorámica y zoom más eficiente en lienzos de tinta grandes
  • Intercalación de tinta y otros objetos, como formas o texto, al tiempo que se mantiene el orden de apilamiento.
  • Secado y conversión de lápiz sincrónicamente en una forma DirectX (por ejemplo, una línea recta o forma rasterizada e integrada en el contenido de la aplicación en lugar de como un inkCanvas independiente capa).

El secado personalizado requiere un objeto IInkD2DRenderer para administrar la entrada de lápiz y representarlo en el contexto del dispositivo Direct2D de la aplicación universal de Windows, en lugar del control InkCanvas predeterminado.

Al llamar a ActivateCustomDrying (antes de que se cargue el InkCanvas), una aplicación crea un objeto InkSynchronizer para personalizar cómo se representa un trazo de tinta al secar en un SurfaceImageSource o VirtualSurfaceImageSource.

Tanto SurfaceImageSource como VirtualSurfaceImageSource proporcionan una superficie compartida de DirectX en la que tu aplicación puede dibujar y componer su contenido. Sin embargo, VSIS ofrece una superficie virtual que es más grande que la pantalla para permitir un desplazamiento y zoom eficientes. Dado que las actualizaciones visuales de estas superficies se sincronizan con el subproceso de la interfaz de usuario XAML, cuando se representa tinta en cualquiera de ellas, la tinta fresca se puede quitar de InkCanvas simultáneamente.

También puede personalizar la tinta seca en un SwapChainPanel, pero no se garantiza la sincronización con el hilo de la interfaz de usuario, y puede haber un retraso entre el momento en que la tinta se renderiza en su SwapChainPanel y cuando se elimina de InkCanvas.

Para obtener un ejemplo completo de esta funcionalidad, consulte la muestra de tinta compleja .

Nota:

Secado personalizado y barra de herramientas de tinta
Si tu aplicación anula el comportamiento predeterminado de representación de tinta del InkPresenter con una implementación de secado personalizada, los trazos de tinta representados ya no estarán disponibles para el InkToolbar y los comandos de borrado integrados del InkToolbar no funcionarán como se espera. Para proporcionar funcionalidad de borrado, debe controlar todos los eventos de puntero, realizar detección de colisiones en cada trazo y sobrescribir el comando integrado "Borrar toda la tinta".

Tema Descripción
reconocer trazos de lápiz Convierta trazos de lápiz en texto mediante el reconocimiento de escritura a mano o en formas mediante el reconocimiento personalizado.
Almacenar y recuperar trazos de tinta Almacene datos de trazos de lápiz en un archivo de formato de intercambio de gráficos (GIF) mediante metadatos incrustados de formato serializado de lápiz (ISF).
Agregar un control InkToolbar a una aplicación de tinta digital de Windows Agregue una InkToolbar predeterminada a una aplicación de Windows para dibujar a mano, añada un botón de lápiz personalizado a la InkToolbar y vincule el botón de lápiz personalizado a una definición de lápiz personalizada.

APIs (Interfaz de Programación de Aplicaciones)

Muestras

Ejemplos de archivo