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

Imagen prominente del Lápiz surface.
Lápiz para Surface (comprar en Microsoft Store).

Información general

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

Nota:

Este tema se centra en la plataforma de Windows Ink. Para obtener un control general de entrada de puntero (similar al mouse, la entrada táctil y el panel táctil), consulte Control de entrada de puntero.

Uso de entrada de lápiz en la aplicación de Windows

Usar lápiz y lápiz de Windows 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 mouse. 

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

Para obtener instrucciones sobre la experiencia de usuario de Windows Ink, consulte Controles de entrada manuscrita.

Componentes de la plataforma Windows Ink

Componente Descripción
InkCanvas Un control de plataforma de UI de XAML que, de manera predeterminada, recibe y muestra toda la entrada de un lápiz como un trazo de entrada manuscrita 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 trazos de Windows Ink.
InkPresenter Un objeto de código subyacente, creado junto con un control de InkCanvas (expuesto mediante la propiedad InkCanvas.InkPresenter). Este objeto proporciona toda la funcionalidad de entrada manuscrita predeterminada expuesta por el control de InkCanvas, junto con un conjunto completo de API para una 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 datos de trazos de Windows Ink.
InkToolbar Un control de plataformas de UI de XAML que contiene una colección personalizable y extensible de botones que activan características relacionadas con las entradas de lápiz en un control de InkCanvas asociado.
Para obtener más información sobre cómo usar InkToolbar, consulte Agregar un control InkToolbar a una aplicación de entrada manuscrita de windows.
IInkD2DRenderer Habilita la representación de trazos de entrada manuscrita en el contexto designado del dispositivo Direct2D de una aplicación universal de Windows, en lugar del control predeterminado de InkCanvas. Esto permite la personalización completa de la experiencia de entrada manuscrita.
Para obtener más información, consulte el ejemplo de entrada de lápiz compleja.

Entrada manuscrita básica con InkCanvas

Para agregar funcionalidad básica de entrada manuscrita, basta con colocar un control de plataforma para UWP inkCanvas en la página adecuada de la 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 lápiz mediante la configuración predeterminada para el color y el grosor (un lápiz de punto de bola negro con un grosor de 2 píxeles) o se trata como borrador de trazo (cuando la entrada procede de una punta del borrador o la punta del lápiz modificada con un botón de borrado).

Nota:

Si no hay ninguna sugerencia o botón de borrador, inkCanvas se puede configurar para procesar la entrada desde la punta del lápiz como un trazo de borrado.

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

Nota:

Un Control InkCanvas tiene las propiedades Height y Width predeterminadas de cero, a menos que sea el elemento secundario de un elemento que ajuste automáticamente el tamaño de sus elementos secundarios, como los controles 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.
InkCanvas en blanco con una imagen de fondo. InkCanvas con trazos de lápiz. InkCanvas con un trazo borrado (tenga en cuenta cómo la borrado funciona en un trazo completo, no en una parte).

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

Para la entrada manuscrita básica, no tiene que preocuparse por inkPresenter. Sin embargo, para personalizar y configurar el comportamiento de entrada manuscrita en InkCanvas, debe tener acceso a su objeto InkPresenter correspondiente.

Personalización básica con InkPresenter

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

Nota:

InkPresenter no se puede crear una instancia directamente. En su lugar, se accede a través de la propiedad InkPresenter de InkCanvas. 

Además de proporcionar todos los comportamientos de entrada manuscrita predeterminados de su control InkCanvas correspondiente, InkPresenter proporciona un conjunto completo de API para la personalización de trazos adicional y la administración más detallada de la entrada del lápiz (estándar y 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 entrada de lápiz solo se admite para la entrada del 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 InkCanvas.

Para habilitar el ratón y la entrada manuscrita táctil, establezca la propiedad InputDeviceTypes de InkPresenter en la combinación de los valores de CoreInputDeviceTypes que quiere.

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 entrada de lápiz.

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

InkCanvas con trazos de lápiz negro predeterminados.

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

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

Para proporcionar funcionalidad más allá de la entrada manuscrita y la borrado, como la selección de trazo, la aplicación debe identificar una entrada específica para que InkPresenter pase a través de un proceso sin procesar para controlarla la aplicación.

Entrada de paso a través 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 funcionalidad adicional para lápices sin prestaciones secundarias (funcionalidad no normalmente asociada con la sugerencia del lápiz), otros tipos de dispositivos de entrada o algún tipo de comportamiento modificado en función de una selección de usuario en la interfaz de usuario de la aplicación.

Para admitir esto, InkPresenter se puede configurar para dejar una entrada específica sin procesar. 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 de InkCanvas) para dibujar el trazo de selección. El uso de una capa independiente para dibujar el trazo de selección deja a InkCanvas y su contenido intacto.

    Captura de pantalla de 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 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 InkPresenter para interpretar los datos de entrada del lápiz y el mouse como trazos de lápiz, y establecemos algunos atributos iniciales de trazos de lápiz usados para representar trazos en 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, 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, PointerMoved y PointerReleased pasados por InkPresenter. Toda la funcionalidad de selección se implementa en los controladores para estos eventos.

    Por último, asignamos agentes de escucha para los eventos StrokeStarted y StrokesErased de 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 entrada de lápiz que muestra inkcanvas con trazos de lápiz negro 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, PointerMoved y PointerReleased pasados por InkPresenter.

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

    Captura de pantalla de la 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 (el trazo lazo) y, a continuación, dibujamos un único rectángulo delimitador alrededor de los trazos de lápiz 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;
        }
      }
    

Personalizar la representación de la entrada manuscrita

De forma predeterminada, la entrada de lápiz se procesa en un subproceso de fondo de baja latencia y se representa en curso, o "mojado", ya que se dibuja. Cuando se completa el trazo (lápiz o movimiento del dedo, o el botón del ratón), el trazo se procesa en el subproceso de interfaz de usuario y se representa como "definitivo" en la capa de InkCanvas (encima del contenido de la aplicación y reemplaza la entrada de lápiz provisional).

Puede invalidar este comportamiento predeterminado y controlar completamente la experiencia de entrada manuscrita mediante el "secado personalizado" de los trazos de lápiz 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 movimiento panorámico y zoom más eficaz en lienzos de lápiz grandes
  • Intercalación de entrada de lápiz y otros objetos, como formas o texto, al tiempo que se mantiene el orden Z
  • 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 una capa InkCanvas independiente).

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 cargar InkCanvas), una aplicación crea un objeto InkSynchronizer para personalizar cómo se representa un trazo de lápiz en un SurfaceImageSource o VirtualSurfaceImageSource.

SurfaceImageSource y VirtualSurfaceImageSource proporcionan una superficie compartida de DirectX para que la aplicación se dibuje y se componga en el contenido de la aplicación, aunque VSIS proporciona una superficie virtual que es mayor que la pantalla para realizar movimiento panorámico y zoom. Dado que las actualizaciones visuales de estas superficies se sincronizan con el subproceso de interfaz de usuario XAML, cuando la entrada de lápiz se representa en cualquiera de ellas, la entrada de lápiz húmeda se puede quitar de InkCanvas simultáneamente.

También puede personalizar la entrada de lápiz seca en un SwapChainPanel, pero no se garantiza la sincronización con el subproceso de la interfaz de usuario y puede haber un retraso entre cuando la entrada de lápiz se representa en el SwapChainPanel y cuando la entrada de lápiz se quita de InkCanvas.

Para obtener un ejemplo completo de esta funcionalidad, consulte el ejemplo de entrada de lápiz compleja.

Nota:

Efecto definitivo personalizado e InkToolbar
Si la aplicación invalida el comportamiento de representación de entrada de lápiz predeterminada de InkPresenter con una implementación de efecto definitivo personalizado, los trazos de entrada manuscrita representados ya no estarán disponibles para InkToolbar y los comandos de borrado integrados de InkToolbar no funcionarán según lo previsto. Para proporcionar funcionalidad de borrado, debe controlar todos los eventos de puntero, hacer pruebas de posicionamiento en cada trazo e invalidar el comando integrado "Borrar toda la entrada de lápiz".

Tema Descripción
Reconocimiento de 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 lápiz 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 entrada manuscrita de Windows Agregue una InkToolbar predeterminada a una aplicación de Windows de entrada manuscrita, agregue un botón de lápiz personalizado a InkToolbar y enlace el botón de lápiz personalizado a una definición de lápiz personalizado.

API existentes

Ejemplos

Ejemplos de archivo