Compartir a través de


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

Imagen destacada del Lápiz Surface.
Lápiz de Surface (disponible para su compra 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 tinta digital en la aplicación de Windows

Utilizar Windows Ink para desarrollar 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 tinta es muy flexible. Está diseñado para admitir varios niveles de funcionalidad, en función de sus requisitos.

Para obtener directrices sobre la experiencia de usuario de Windows Ink, consulte Controles de tinta.

Componentes de la plataforma Windows Ink

Componente Description
InkCanvas Un control de plataforma de interfaz de usuario XAML que, de forma predeterminada, recibe y muestra todas las entradas 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 trazos de Windows Ink.
InkPresenter Objeto de código subyacente, creado junto con un control InkCanvas (expuesto a través de la propiedad InkCanvas.InkPresenter ). Este objeto proporciona toda la funcionalidad de entrada manuscrita predeterminada expuesta por InkCanvas, junto con un conjunto completo de APIs para una mayor personalización y adaptación.
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 Control de plataforma de interfaz de usuario XAML que contiene una colección personalizable y extensible de botones que activan funciones relacionadas con la tinta en un control InkCanvas asociado.
Para obtener más información sobre cómo usar InkToolbar, consulte Agregar un control InkToolbar a una aplicación para escritura manual de Windows.
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 tinta digital.
Para obtener más información, consulte la muestra de tinta compleja.

Tinta digital 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 tinta mediante 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 trazos (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 punta de borrador o botón, InkCanvas se puede configurar para procesar la entrada desde la punta del lápiz como un trazo de borrado.

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

Nota:

Un InkCanvas tiene las propiedades de Height y Width predeterminadas de cero, a menos que sea un elemento secundario de un elemento que ajusta 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 (observe cómo el proceso de borrado se realiza en un trazo completo, no en una parte).

La funcionalidad de tinta admitida por el control InkCanvas se proporciona mediante un objeto de código detrás denominado InkPresenter.

Para la entrada manuscrita básica, no tiene que preocuparse por el 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 instancia un objeto InkPresenter con cada control InkCanvas.

Nota:

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

Además de proporcionar todos los comportamientos predeterminados de tinta de su control InkCanvas correspondiente, InkPresenter proporciona un conjunto completo de APIs para la personalización adicional de trazos y la administración más detallada de la entrada del lápiz, 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 del borrador) no se modifica con una prestación de hardware secundaria, como un botón lateral del lápiz, un botón derecho del ratón o un mecanismo similar.

De forma predeterminada, al usar un lápiz, solo se admite la entrada de tinta. 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 el entintado táctil, establezca la propiedad InputDeviceTypes de InkPresenter a la combinación de valores CoreInputDeviceTypes que desee.

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í, permitimos 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.

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 el borrado, como la selección de trazos, la aplicación debe identificar una entrada específica para que InkPresenter pase sin procesar para ser controlada por la 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 funcionalidades secundarias (funcionalidad no normalmente asociada con la punta del lápiz), otros tipos de dispositivos de entrada o algún tipo de comportamiento modificado basado en una selección del usuario en la interfaz de usuario de tu 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 datos de entrada sin procesar para realizar 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 del 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 transfiere a la clase InkUnprocessedInput un conjunto de eventos de puntero para que los manejes.

    Asignamos escuchas para los eventos PointerPressed, PointerMoved y PointerReleased sin procesar 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 muestra de personalización avanzada de tinta que muestra el inkcanvas 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, 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 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 todo el contenido de la capa de selección (el trazo de 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.

    Tanto uno como otro 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 entrada de lápiz personalizada

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

Puede invalidar este comportamiento predeterminado y controlar completamente la experiencia de la tinta digital 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 más eficaz con el movimiento panorámico y el zoom en grandes lienzos de tinta.
  • Intercalación de tinta y otros objetos, como formas o texto, manteniendo el orden Z
  • Secado de la tinta y su conversión sincrónicamente en una forma de DirectX (por ejemplo, una línea recta o una forma rasterizada e integrada en el contenido de la aplicación, en vez 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 que se cargue InkCanvas), la aplicación crea un objeto InkSynchronizer para personalizar cómo un trazo de tinta se presenta seco en un SurfaceImageSource o VirtualSurfaceImageSource.

SurfaceImageSource y VirtualSurfaceImageSource proporcionan una superficie compartida de DirectX para que tu aplicación dibuje en ella y se componga en el contenido de la aplicación, aunque VSIS proporciona una superficie virtual que es más grande que la pantalla para un desplazamiento y zoom más eficientes. Dado que las actualizaciones visuales de estas superficies se sincronizan con el subproceso de interfaz de usuario XAML, cuando la tinta se representa en cualquiera de ellas, la tinta húmeda 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 subproceso de la interfaz de usuario y puede haber un retraso entre cuando la tinta se representa en el SwapChainPanel y cuando se elimina del InkCanvas.

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

Nota:

Secado personalizado y InkToolbar
Si la aplicación invalida el comportamiento de representación de entrada de lápiz predeterminada de InkPresenter con una implementación de secado personalizada, los trazos de lápiz 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, realizar pruebas de impacto en cada trazo y sobrescribir el comando integrado "Borrar toda la tinta digital".

Tema Description
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 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 una barra de herramientas de tinta a una aplicación para escritura a mano de Windows Agregue un InkToolbar predeterminado a una aplicación de inking de Windows, agregue un botón de lápiz personalizado al 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)

Samples

Ejemplos de archivo