Freigeben über


Hinzufügen einer InkToolbar zu einer Windows-App

Es gibt zwei verschiedene Steuerelemente, die die Freihandeingabe in Windows-Apps erleichtern: InkCanvas und InkToolbar.

Das InkCanvas-Steuerelement bietet grundlegende Windows Ink-Funktionen. Verwenden Sie es zum Rendern von Stifteingaben als Tintenstrich (unter Verwendung von Standardeinstellungen für Farbe und Stärke) oder als Löschenstrich.

Details zur InkCanvas-Implementierung finden Sie unter Stift- und Eingabestiftinteraktionen in Windows-Apps.

Als vollständig transparente Überlagerung bietet das InkCanvas keine integrierte Benutzeroberfläche zum Festlegen von Tintenstricheigenschaften. Wenn Sie die standardmäßige Freihandeingabefunktion ändern möchten, Benutzer Freihandstricheigenschaften festlegen und andere benutzerdefinierte Freihandfunktionen unterstützen, haben Sie zwei Optionen:

  • Verwenden Sie im Code-Behind das zugrunde liegende InkPresenter-Objekt, das an den InkCanvas gebunden ist.

    Die InkPresenter-APIs unterstützen umfangreiche Anpassungen der Freihandeingabe.The InkPresenter APIs support extensive customization of the inking experience. Weitere Details finden Sie unter Zeichen- und Eingabestiftinteraktionen in Windows-Apps.

  • Binden Sie eine InkToolbar an den InkCanvas. Standardmäßig bietet die InkToolbar eine anpassbare und erweiterbare Sammlung von Schaltflächen zum Aktivieren von Freihandfunktionen wie Strichstärke, Stiftfarbe und Stiftspitze.

    Wir besprechen die InkToolbar in diesem Thema.

Wichtige APIs: InkCanvas-Klasse, InkToolbar-Klasse, InkPresenter-Klasse, Windows.UI.Input.Inking

Standard inkToolbar

Standardmäßig enthält die InkToolbar Schaltflächen zum Zeichnen, Löschen, Hervorheben und Anzeigen einer Schablone (Lineal oder Protractor). Abhängig vom Feature werden weitere Einstellungen und Befehle, z.B. für Farbe, Strichstärke und das Löschen aller Elemente, in einem Flyout bereitgestellt.

InkToolbar
Standardmäßige Windows Ink-Symbolleiste

Wenn Sie einer Zeichen-App eine Standard-InkToolbar hinzufügen möchten, platzieren Sie sie einfach auf derselben Seite wie Ihr InkCanvas und verknüpfen Sie die beiden Steuerungselemente.

  1. Deklarieren Sie in "MainPage.xaml" ein Containerobjekt (für dieses Beispiel verwenden wir ein Grid-Steuerelement) für die Eingabefläche der Freihandzeichnung.
  2. Deklarieren Sie ein InkCanvas-Objekt als untergeordnetes Element des Containers. (Die InkCanvas-Größe wird vom Container geerbt.)
  3. Deklarieren Sie eine InkToolbar, und verwenden Sie das TargetInkCanvas-Attribut, um es an "InkCanvas" zu binden.

Hinweis

Stellen Sie sicher, dass die InkToolbar nach dem InkCanvas deklariert wird. Wenn nicht, macht die InkCanvas-Überlagerung die InkToolbar unzugänglich.

<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" />
        <InkToolbar x:Name="inkToolbar"
          VerticalAlignment="Top"
          TargetInkCanvas="{x:Bind inkCanvas}" />
    </Grid>
</Grid>

Grundlegende Anpassung

In diesem Abschnitt behandeln wir einige grundlegende Anpassungsszenarien für die Windows Ink-Symbolleiste.

Standort und Ausrichtung angeben

Wenn Sie Ihrer App eine Ink-Symbolleiste hinzufügen, können Sie den Standardstandort und die Standardausrichtung der Symbolleiste akzeptieren oder sie nach Bedarf für Ihre App oder den Benutzer festlegen.

XAML

Geben Sie explizit die Position und Ausrichtung der Symbolleiste über die Eigenschaften VerticalAlignment, HorizontalAlignment und Orientation an.

Standard Explicit
Standardposition und Ausrichtung der Ink-Symbolleiste Explizite Freihandsymbolleistenposition und -ausrichtung
Standardposition und Ausrichtung der Windows Ink-Symbolleiste Explizite Position und Ausrichtung der Windows Ink-Symbolleiste

Hier ist der Code zum expliziten Festlegen der Position und Ausrichtung der Freihandsymbolleiste in XAML.

<InkToolbar x:Name="inkToolbar" 
    VerticalAlignment="Center" 
    HorizontalAlignment="Right" 
    Orientation="Vertical" 
    TargetInkCanvas="{x:Bind inkCanvas}" />

Initialisieren basierend auf Benutzereinstellungen oder Gerätestatus

In einigen Fällen möchten Sie möglicherweise die Position und Ausrichtung der Freihandsymbolleiste basierend auf den Benutzereinstellungen oder dem Gerätezustand festlegen. Im folgenden Beispiel wird veranschaulicht, wie Sie die Position und Ausrichtung der Freihandsymbolleiste basierend auf den Einstellungen für links- oder rechtshändige Schreibeinstellungen festlegen, die über Einstellungen Geräte Stift & Windows Ink Stift Wählen Sie aus, mit welcher Hand Sie schreiben festgelegt sind.

Einstellung für die dominante Hand
Einstellung für die dominante Hand

Sie können diese Einstellung über die HandPreference-Eigenschaft von Windows.UI.ViewManagement abfragen und das HorizontalAlignment basierend auf dem zurückgegebenen Wert festlegen. In diesem Beispiel wird die Symbolleiste auf der linken Seite der App für eine linkshändige Person und auf der rechten Seite für eine rechtshändige Person gefunden.

Laden Sie das Beispiel für Speicherort und Ausrichtung der Stift-Symbolleiste (einfach) herunter

public MainPage()
{
    this.InitializeComponent();

    Windows.UI.ViewManagement.UISettings settings = 
        new Windows.UI.ViewManagement.UISettings();
    HorizontalAlignment alignment = 
        (settings.HandPreference == 
            Windows.UI.ViewManagement.HandPreference.LeftHanded) ? 
            HorizontalAlignment.Left : HorizontalAlignment.Right;
    inkToolbar.HorizontalAlignment = alignment;
}

Dynamische Anpassung an den Benutzer- oder Gerätestatus

Sie können die Bindung auch verwenden, um UI-Updates zu betreuen, die auf Änderungen an Benutzereinstellungen, Geräteeinstellungen oder Gerätezuständen basieren. Im folgenden Beispiel erweitern wir das vorherige Beispiel und zeigen, wie die Freihandsymbolleiste dynamisch basierend auf der Geräteausrichtung mithilfe von Datenbindung, einem ViewModel-Objekt und der INotifyPropertyChanged-Schnittstelle positioniert wird.

Laden Sie dieses Beispiel aus dem Freihandsymbolleiste-Standort und der Ausrichtung (dynamisch) herunter.

  1. Als Erstes fügen wir unser ViewModel hinzu.

    1. Fügen Sie Ihrem Projekt einen neuen Ordner hinzu, und nennen Sie ihn ViewModels.

    2. Fügen Sie dem Ordner "ViewModels" eine neue Klasse hinzu (in diesem Beispiel haben wir sie InkToolbarSnippetHostViewModel.cs genannt).

      Hinweis

      Wir haben das Singleton-Muster verwendet, da wir nur ein Objekt dieses Typs für die Lebensdauer der Anwendung benötigen.

    3. Fügen Sie den Namespace using System.ComponentModel der Datei hinzu.

    4. Fügen Sie eine statische Membervariable namens "Instanz" und eine statische schreibgeschützte Eigenschaft namens "Instance" hinzu. Machen Sie den Konstruktor privat, um sicherzustellen, dass nur über die Instance-Eigenschaft auf diese Klasse zugegriffen werden kann.

      Hinweis

      Diese Klasse erbt von der INotifyPropertyChanged-Schnittstelle, die verwendet wird, um Clients, in der Regel gebundene Clients, zu benachrichtigen, dass sich ein Eigenschaftswert geändert hat. Wir verwenden dies, um Änderungen an der Geräteausrichtung zu behandeln (wir werden diesen Code erweitern und in einem späteren Schritt weiter erläutern).

      using System.ComponentModel;
      
      namespace locationandorientation.ViewModels
      {
          public class InkToolbarSnippetHostViewModel : INotifyPropertyChanged
          {
              private static InkToolbarSnippetHostViewModel instance;
      
              public static InkToolbarSnippetHostViewModel Instance
              {
                  get
                  {
                      if (null == instance)
                      {
                          instance = new InkToolbarSnippetHostViewModel();
                      }
                      return instance;
                  }
              }
          }
      
          private InkToolbarSnippetHostViewModel() { }
      }
      
    5. Fügen Sie der InkToolbarSnippetHostViewModel-Klasse zwei boolische Eigenschaften hinzu: LeftHandedLayout (gleiche Funktionalität wie im vorherigen XAML-only-Beispiel) und PortraitLayout (Ausrichtung des Geräts).

      Hinweis

      Die PortraitLayout-Eigenschaft ist festgelegt und enthält die Definition für das PropertyChanged-Ereignis .

      public bool LeftHandedLayout
      {
          get
          {
              bool leftHandedLayout = false;
              Windows.UI.ViewManagement.UISettings settings =
                  new Windows.UI.ViewManagement.UISettings();
              leftHandedLayout = (settings.HandPreference ==
                  Windows.UI.ViewManagement.HandPreference.LeftHanded);
              return leftHandedLayout;
          }
      }
      
      public bool portraitLayout = false;
      public bool PortraitLayout
      {
          get
          {
              Windows.UI.ViewManagement.ApplicationViewOrientation winOrientation = 
                  Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().Orientation;
              portraitLayout = 
                  (winOrientation == 
                      Windows.UI.ViewManagement.ApplicationViewOrientation.Portrait);
              return portraitLayout;
          }
          set
          {
              if (value.Equals(portraitLayout)) return;
              portraitLayout = value;
              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PortraitLayout"));
          }
      }
      
  2. Nun fügen wir unserem Projekt einige Konverterklassen hinzu. Jede Klasse enthält ein Convert-Objekt, das einen Ausrichtungswert zurückgibt ( entweder HorizontalAlignment oder VerticalAlignment).

    1. Fügen Sie Ihrem Projekt einen neuen Ordner hinzu, und nennen Sie ihn "Converters".

    2. Fügen Sie dem Ordner "Converters" zwei neue Klassen hinzu (in diesem Beispiel nennen wir sie HorizontalAlignmentFromHandednessConverter.cs und VerticalAlignmentFromAppViewConverter.cs).

    3. Fügen Sie zu jeder Datei die using Windows.UI.Xaml- und using Windows.UI.Xaml.Data-Namespaces hinzu.

    4. Ändern Sie jede Klasse in public und geben Sie an, dass sie die IValueConverter-Schnittstelle implementiert.

    5. Fügen Sie die Convert - und ConvertBack-Methoden zu jeder Datei hinzu, wie hier gezeigt (wir lassen die ConvertBack-Methode nicht implementiert).

      • HorizontalAlignmentFromHandednessConverter positioniert die Freihandsymbolleiste für rechtshändige Nutzer auf der rechten Seite der App und für linkshändige Nutzer auf der linken Seite der App.
      using System;
      
      using Windows.UI.Xaml;
      using Windows.UI.Xaml.Data;
      
      namespace locationandorientation.Converters
      {
          public class HorizontalAlignmentFromHandednessConverter : IValueConverter
          {
              public object Convert(object value, Type targetType,
                  object parameter, string language)
              {
                  bool leftHanded = (bool)value;
                  HorizontalAlignment alignment = HorizontalAlignment.Right;
                  if (leftHanded)
                  {
                      alignment = HorizontalAlignment.Left;
                  }
                  return alignment;
              }
      
              public object ConvertBack(object value, Type targetType,
                  object parameter, string language)
              {
                  throw new NotImplementedException();
              }
          }
      }
      
      • VerticalAlignmentFromAppViewConverter positioniert die Freihand-Werkzeugleiste in der Mitte der App bei Hochformat-Ausrichtung und an der oberen Kante der App bei Querformat-Ausrichtung (obwohl diese Anordnung die Benutzerfreundlichkeit verbessern soll, handelt es sich nur um eine beliebige Wahl für Demonstrationszwecke).
      using System;
      
      using Windows.UI.Xaml;
      using Windows.UI.Xaml.Data;
      
      namespace locationandorientation.Converters
      {
          public class VerticalAlignmentFromAppViewConverter : IValueConverter
          {
              public object Convert(object value, Type targetType,
                  object parameter, string language)
              {
                  bool portraitOrientation = (bool)value;
                  VerticalAlignment alignment = VerticalAlignment.Top;
                  if (portraitOrientation)
                  {
                      alignment = VerticalAlignment.Center;
                  }
                  return alignment;
              }
      
              public object ConvertBack(object value, Type targetType,
                  object parameter, string language)
              {
                  throw new NotImplementedException();
              }
          }
      }
      
  3. Öffnen Sie nun die MainPage.xaml.cs Datei.

    1. Fügen Sie using using locationandorientation.ViewModels der Liste der Namespaces hinzu, um unser ViewModel zuzuordnen.
    2. Fügen Sie using Windows.UI.ViewManagement der Liste der Namespaces hinzu, um das Überwachen von Änderungen an der Geräteausrichtung zu ermöglichen.
    3. Fügen Sie den WindowSizeChangedEventHandler-Code hinzu.
    4. Legen Sie den DataContext für die Ansicht auf die Singleton-Instanz der InkToolbarSnippetHostViewModel-Klasse fest.
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    
    using locationandorientation.ViewModels;
    using Windows.UI.ViewManagement;
    
    namespace locationandorientation
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
    
                Window.Current.SizeChanged += (sender, args) =>
                {
                    ApplicationView currentView = ApplicationView.GetForCurrentView();
    
                    if (currentView.Orientation == ApplicationViewOrientation.Landscape)
                    {
                        InkToolbarSnippetHostViewModel.Instance.PortraitLayout = false;
                    }
                    else if (currentView.Orientation == ApplicationViewOrientation.Portrait)
                    {
                        InkToolbarSnippetHostViewModel.Instance.PortraitLayout = true;
                    }
                };
    
                DataContext = InkToolbarSnippetHostViewModel.Instance;
            }
        }
    }
    
  4. Öffnen Sie als Nächstes die Datei "MainPage.xaml".

    1. Fügen Sie xmlns:converters="using:locationandorientation.Converters" dem Page-Element hinzu, um es an unsere Konverter zu binden.

      <Page
      x:Class="locationandorientation.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:locationandorientation"
      xmlns:converters="using:locationandorientation.Converters"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">
      
    2. Fügen Sie ein PageResources Element hinzu, und geben Sie Verweise auf unsere Konverter an.

      <Page.Resources>
          <converters:HorizontalAlignmentFromHandednessConverter x:Key="HorizontalAlignmentConverter"/>
          <converters:VerticalAlignmentFromAppViewConverter x:Key="VerticalAlignmentConverter"/>
      </Page.Resources>
      
    3. Fügen Sie die Elemente InkCanvas und InkToolbar hinzu, und binden Sie die Eigenschaften VerticalAlignment und HorizontalAlignment der InkToolbar.

      <InkCanvas x:Name="inkCanvas" />
      <InkToolbar x:Name="inkToolbar" 
                  VerticalAlignment="{Binding PortraitLayout, Converter={StaticResource VerticalAlignmentConverter} }" 
                  HorizontalAlignment="{Binding LeftHandedLayout, Converter={StaticResource HorizontalAlignmentConverter} }" 
                  Orientation="Vertical" 
                  TargetInkCanvas="{x:Bind inkCanvas}" />
      
  5. Kehren Sie zur InkToolbarSnippetHostViewModel.cs-Datei zurück, um unsere PortraitLayout und LeftHandedLayout bool-Eigenschaften zur InkToolbarSnippetHostViewModel Klasse hinzuzufügen, und die Unterstützung für das Neubinden von PortraitLayout, wenn sich der Wert dieser Eigenschaft ändert.

    public bool LeftHandedLayout
    {
        get
        {
            bool leftHandedLayout = false;
            Windows.UI.ViewManagement.UISettings settings =
                new Windows.UI.ViewManagement.UISettings();
            leftHandedLayout = (settings.HandPreference ==
                Windows.UI.ViewManagement.HandPreference.LeftHanded);
            return leftHandedLayout;
        }
    }
    
    public bool portraitLayout = false;
    public bool PortraitLayout
    {
        get
        {
            Windows.UI.ViewManagement.ApplicationViewOrientation winOrientation = 
                Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().Orientation;
            portraitLayout = 
                (winOrientation == 
                    Windows.UI.ViewManagement.ApplicationViewOrientation.Portrait);
            return portraitLayout;
        }
        set
        {
            if (value.Equals(portraitLayout)) return;
            portraitLayout = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PortraitLayout"));
        }
    }
    
    #region INotifyPropertyChanged Members
    
    public event PropertyChangedEventHandler PropertyChanged;
    
    protected void OnPropertyChanged(string property)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }
    
    #endregion
    

Sie sollten jetzt über eine Zeichen-App verfügen, die sich sowohl an die Handpräferenz des Nutzers anpasst als auch dynamisch auf die Ausrichtung des Nutzergeräts reagiert.

Angeben der ausgewählten Schaltfläche

Bleistiftschaltfläche bei der Initialisierung ausgewählt
Windows Ink-Symbolleiste mit ausgewählter Bleistiftschaltfläche bei der Initialisierung

Standardmäßig wird die erste Schaltfläche (oder ganz links) ausgewählt, wenn Ihre App gestartet wird und die Symbolleiste initialisiert wird. In der Standardmäßigen Windows Ink-Symbolleiste ist dies die Kugelschreiberschaltfläche.

Da das Framework die Reihenfolge der integrierten Schaltflächen definiert, ist die erste Schaltfläche möglicherweise nicht der Stift oder das Tool, das Sie standardmäßig aktivieren möchten.

Sie können dieses Standardverhalten außer Kraft setzen und die ausgewählte Schaltfläche auf der Symbolleiste angeben.

In diesem Beispiel initialisieren wir die Standardsymbolleiste mit ausgewählter Stiftschaltfläche und aktiviertem Bleistift (anstelle des Kugelschreibers).

  1. Verwenden Sie die XAML-Deklaration für inkCanvas und InkToolbar aus dem vorherigen Beispiel.
  2. Richten Sie im CodeBehind einen Handler für das Loaded-Ereignis des InkToolbar-Objekts ein.
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// Here, we set up InkToolbar event listeners.
/// </summary>
public MainPage_CodeBehind()
{
    this.InitializeComponent();
    // Add handlers for InkToolbar events.
    inkToolbar.Loaded += inkToolbar_Loaded;
}
  1. Im Handler für das Loaded-Ereignis :

    1. Rufen Sie einen Verweis auf den integrierten InkToolbarPencilButton ab.

    Durch Übergeben eines InkToolbarTool.Pencil-Objekts in der GetToolButton-Methode wird ein InkToolbarToolButton -Objekt für das InkToolbarPencilButton-Objekt zurückgegeben.

    1. Legen Sie ActiveTool auf das im vorherigen Schritt zurückgegebene Objekt fest.
/// <summary>
/// Handle the Loaded event of the InkToolbar.
/// By default, the active tool is set to the first tool on the toolbar.
/// Here, we set the active tool to the pencil button.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void inkToolbar_Loaded(object sender, RoutedEventArgs e)
{
    InkToolbarToolButton pencilButton = inkToolbar.GetToolButton(InkToolbarTool.Pencil);
    inkToolbar.ActiveTool = pencilButton;
}

Angeben der integrierten Schaltflächen

Bestimmte Schaltflächen, die bei der Initialisierung enthalten sind
Bestimmte Schaltflächen, die bei der Initialisierung enthalten sind

Wie bereits erwähnt, enthält die Windows Ink-Symbolleiste eine Sammlung von standardmäßigen integrierten Schaltflächen. Diese Schaltflächen werden in der folgenden Reihenfolge angezeigt (von links nach rechts):

In diesem Beispiel initialisieren wir die Symbolleiste nur mit den integrierten Kugelschreiber-, Bleistift- und Radiererschaltflächen.

Dazu können Sie ENTWEDER XAML oder CodeBehind verwenden.

XAML

Ändern Sie die XAML-Deklaration für inkCanvas und InkToolbar aus dem ersten Beispiel.

Hinweis

Schaltflächen werden der Symbolleiste in der durch das Framework definierten Reihenfolge und nicht der hier angegebenen Reihenfolge hinzugefügt.

<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" />
        <!-- Clear the default InkToolbar buttons by setting InitialControls to None. -->
        <!-- Set the active tool to the pencil button. -->
        <InkCanvas x:Name="inkCanvas" />
        <InkToolbar x:Name="inkToolbar"
                    VerticalAlignment="Top"
                    TargetInkCanvas="{x:Bind inkCanvas}"
                    InitialControls="None">
            <!--
             Add only the ballpoint pen, pencil, and eraser.
             Note that the buttons are added to the toolbar in the order
             defined by the framework, not the order we specify here.
            -->
            <InkToolbarEraserButton />
            <InkToolbarBallpointPenButton />
            <InkToolbarPencilButton/>
        </InkToolbar>
    </Grid>
</Grid>

CodeBehind

  1. Verwenden Sie die XAML-Deklaration für inkCanvas und InkToolbar aus dem ersten Beispiel.
<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" />
        <InkToolbar x:Name="inkToolbar"
        VerticalAlignment="Top"
        TargetInkCanvas="{x:Bind inkCanvas}" />
    </Grid>
</Grid>
  1. Richten Sie im CodeBehind einen Handler für das Loading-Ereignis des InkToolbar-Objekts ein.
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// Here, we set up InkToolbar event listeners.
/// </summary>
public MainPage_CodeBehind()
{
    this.InitializeComponent();
    // Add handlers for InkToolbar events.
    inkToolbar.Loading += inkToolbar_Loading;
}
  1. Legen Sie InitialControls auf "None" fest.
  2. Erstellen Sie Objektverweise für die schaltflächen, die von Ihrer App benötigt werden. Hier fügen wir nur InkToolbarBallpointPenButton, InkToolbarPencilButton und InkToolbarEraserButton hinzu.

Hinweis

Schaltflächen werden der Symbolleiste in der durch das Framework definierten Reihenfolge und nicht der hier angegebenen Reihenfolge hinzugefügt.

  1. Fügen Sie die Schaltflächen zur InkToolbar hinzu.
/// <summary>
/// Handles the Loading event of the InkToolbar.
/// Here, we identify the buttons to include on the InkToolbar.
/// </summary>
/// <param name="sender">The InkToolbar</param>
/// <param name="args">The InkToolbar event data.
/// If there is no event data, this parameter is null</param>
private void inkToolbar_Loading(FrameworkElement sender, object args)
{
    // Clear all built-in buttons from the InkToolbar.
    inkToolbar.InitialControls = InkToolbarInitialControls.None;

    // Add only the ballpoint pen, pencil, and eraser.
    // Note that the buttons are added to the toolbar in the order
    // defined by the framework, not the order we specify here.
    InkToolbarBallpointPenButton ballpoint = new InkToolbarBallpointPenButton();
    InkToolbarPencilButton pencil = new InkToolbarPencilButton();
    InkToolbarEraserButton eraser = new InkToolbarEraserButton();
    inkToolbar.Children.Add(eraser);
    inkToolbar.Children.Add(ballpoint);
    inkToolbar.Children.Add(pencil);
}

Benutzerdefinierte Schaltflächen und Tintenfunktionen

Sie können die Sammlung von Schaltflächen (und zugehörigen Freihandfunktionen) anpassen und erweitern, die über die InkToolbar bereitgestellt werden.

Die InkToolbar besteht aus zwei unterschiedlichen Gruppen von Schaltflächentypen:

  1. Eine Gruppe von „Tool“-Schaltflächen, die die integrierten Zeichnungs-, Lösch- und Hervorhebungsschaltflächen enthalten. Hier werden benutzerdefinierte Stifte und Tools hinzugefügt.

Anmerkung Die Featureauswahl schließt sich gegenseitig aus.

  1. Eine Gruppe von „Umschaltflächen“, die die integrierte Linealschaltfläche enthalten. Hier werden benutzerdefinierte Umschaltflächen hinzugefügt.

Anmerkung Features schließen sich nicht gegenseitig aus und können gleichzeitig mit anderen aktiven Tools verwendet werden.

Je nach Anwendung und erforderlicher Freihandfunktion können Sie eine der folgenden Schaltflächen (gebunden an Ihre benutzerdefinierten Freihandfeatures) zur InkToolbar hinzufügen:

  • Benutzerdefinierter Stift – ein Stift, für den die Farbpaletten- und Stiftspitzeneigenschaften wie Form, Drehung und Größe von der Host-App definiert werden.
  • Benutzerdefiniertes Tool – ein Nicht-Stift-Tool, das von der Host-App definiert wird.
  • Benutzerdefinierte Umschaltfläche – Legt den Status eines App-definierten Features auf ein oder aus fest. Wenn sie aktiviert ist, funktioniert das Feature in Verbindung mit dem aktiven Tool.

Anmerkung Sie können die Anzeigereihenfolge der integrierten Schaltflächen nicht ändern. Die Standardanzeigereihenfolge lautet: Kugelschreiber, Bleistift, Textmarker, Radierer und Lineal. Benutzerdefinierte Stifte werden an den letzten Standardstift angefügt, benutzerdefinierte Toolschaltflächen werden zwischen der letzten Stiftschaltfläche und der Radiererschaltfläche und benutzerdefinierte Umschaltflächen nach der Linealschaltfläche hinzugefügt. (Benutzerdefinierte Schaltflächen werden in der angegebenen Reihenfolge hinzugefügt.)

Benutzerdefinierter Stift

Sie können einen benutzerdefinierten Stift (aktiviert über eine benutzerdefinierte Stiftschaltfläche) erstellen, in dem Sie die Farbpalette und die Stiftspitze-Eigenschaften wie Form, Drehung und Größe definieren.

Benutzerdefinierte Beschriftungsstiftschaltfläche
Benutzerdefinierte Beschriftungsstiftschaltfläche

In diesem Beispiel definieren wir einen benutzerdefinierten Stift mit einer breiten Spitze, die einfache calliographische Freihandstriche ermöglicht. Außerdem passen wir die Sammlung von Pinseln in der Palette an, die im Schaltflächen-Flyout angezeigt wird.

CodeBehind

Zunächst definieren wir unseren benutzerdefinierten Stift und geben die Zeichnungsattribute in CodeBehind an. Später verweisen wir auf diesen benutzerdefinierten Stift aus XAML.

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie "Hinzufügen –> Neues Element" aus.
  2. Fügen Sie unter Visual C# -> Code eine neue Klassendatei hinzu, und rufen Sie sie CalligraphicPen.cs auf.
  3. Ersetzen Sie in Calligraphic.cs den Standard-using-Block durch folgendes:
using System.Numerics;
using Windows.UI;
using Windows.UI.Input.Inking;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
  1. Geben Sie an, dass die CalligraphicPen-Klasse von InkToolbarCustomPen abgeleitet wird.
class CalligraphicPen : InkToolbarCustomPen
{
}
  1. Überschreiben Sie CreateInkDrawingAttributesCore , um Ihre eigene Pinsel- und Strichgröße anzugeben.
class CalligraphicPen : InkToolbarCustomPen
{
    protected override InkDrawingAttributes
      CreateInkDrawingAttributesCore(Brush brush, double strokeWidth)
    {
    }
}
  1. Erstellen Sie ein InkDrawingAttributes-Objekt , und legen Sie die Form der Stiftspitze, die Drehung, die Strichgröße und die Freihandfarbe fest.
class CalligraphicPen : InkToolbarCustomPen
{
    protected override InkDrawingAttributes
      CreateInkDrawingAttributesCore(Brush brush, double strokeWidth)
    {
        InkDrawingAttributes inkDrawingAttributes =
          new InkDrawingAttributes();
        inkDrawingAttributes.PenTip = PenTipShape.Circle;
        inkDrawingAttributes.Size =
          new Windows.Foundation.Size(strokeWidth, strokeWidth * 20);
        SolidColorBrush solidColorBrush = brush as SolidColorBrush;
        if (solidColorBrush != null)
        {
            inkDrawingAttributes.Color = solidColorBrush.Color;
        }
        else
        {
            inkDrawingAttributes.Color = Colors.Black;
        }

        Matrix3x2 matrix = Matrix3x2.CreateRotation(45);
        inkDrawingAttributes.PenTipTransform = matrix;

        return inkDrawingAttributes;
    }
}

XAML

Als Nächstes fügen wir die erforderlichen Verweise auf den benutzerdefinierten Stift in "MainPage.xaml" hinzu.

  1. Wir deklarieren ein ressourcenwörterbuch für lokale Seiten, das einen Verweis auf den in CalligraphicPen.cs definierten benutzerdefinierten Stift (CalligraphicPen) und eine Pinselauflistung erstellt, die vom benutzerdefinierten Stift (CalligraphicPenPalette) unterstützt wird.
<Page.Resources>
    <!-- Add the custom CalligraphicPen to the page resources. -->
    <local:CalligraphicPen x:Key="CalligraphicPen" />
    <!-- Specify the colors for the palette of the custom pen. -->
    <BrushCollection x:Key="CalligraphicPenPalette">
        <SolidColorBrush Color="Blue" />
        <SolidColorBrush Color="Red" />
    </BrushCollection>
</Page.Resources>
  1. Anschließend fügen wir ein InkToolbar-Element mit einem untergeordneten InkToolbarCustomPenButton-Element hinzu.

Die benutzerdefinierte Stiftschaltfläche enthält die beiden statischen Ressourcenverweise, die in den Seitenressourcen deklariert sind: CalligraphicPen und CalligraphicPenPalette.

Außerdem geben wir den Bereich für den Schieberegler für die Strichgröße (MinStrokeWidth, MaxStrokeWidth und SelectedStrokeWidth), den ausgewählten Pinsel (SelectedBrushIndex) und das Symbol für die benutzerdefinierte Stiftschaltfläche (SymbolIcon) an.

<Grid Grid.Row="1">
    <InkCanvas x:Name="inkCanvas" />
    <InkToolbar x:Name="inkToolbar"
                VerticalAlignment="Top"
                TargetInkCanvas="{x:Bind inkCanvas}">
        <InkToolbarCustomPenButton
            CustomPen="{StaticResource CalligraphicPen}"
            Palette="{StaticResource CalligraphicPenPalette}"
            MinStrokeWidth="1" MaxStrokeWidth="3" SelectedStrokeWidth="2"
            SelectedBrushIndex ="1">
            <SymbolIcon Symbol="Favorite" />
            <InkToolbarCustomPenButton.ConfigurationContent>
                <InkToolbarPenConfigurationControl />
            </InkToolbarCustomPenButton.ConfigurationContent>
        </InkToolbarCustomPenButton>
    </InkToolbar>
</Grid>

Benutzerdefinierter Umschalter

Sie können einen benutzerdefinierten Umschalter (aktiviert über eine benutzerdefinierte Umschaltfläche) erstellen, um den Status eines app-definierten Features auf ein- oder auszuschalten. Wenn sie aktiviert ist, funktioniert das Feature in Verbindung mit dem aktiven Tool.

In diesem Beispiel definieren wir eine benutzerdefinierte Umschalttaste, die Freihandeingaben per Touch-Eingabe ermöglicht (standardmäßig sind Touch-Freihandeingaben nicht aktiviert).

Hinweis

Wenn die Unterstützung von Freihandeingaben mit Toucheingabe erforderlich ist, empfehlen wir, dass Sie sie mithilfe eines *CustomToggleButton*-Steuerelements mit dem in diesem Beispiel angegebenen Symbol und der QuickInfo aktivieren.

In der Regel wird die Toucheingabe für die direkte Manipulation eines Objekts oder der App-UI verwendet. Um die Verhaltensunterschiede bei aktivierter Touch-Inking-Funktion zu veranschaulichen, platzieren wir den InkCanvas in einem ScrollViewer-Container und legen die Abmessungen des ScrollViewer so fest, dass sie kleiner sind als der InkCanvas.

Beim Starten der App wird nur die Stifteingabe unterstützt, und die Toucheingabe dient dazu, die Zeichenfläche zu verschieben oder zu zoomen. Wenn die Freihandeingabe aktiviert ist, kann die Freihandoberfläche nicht über die Toucheingabe verschoben oder vergrößert werden.

Hinweis

Siehe Freihandsteuerelemente für die UX-Richtlinien zu sowohl InkCanvas als auch InkToolbar. Die folgenden Empfehlungen sind für dieses Beispiel relevant:

  • Die InkToolbar und die Freihandeingabe im Allgemeinen werden am besten durch einen aktiven Stift erlebt. Freihandeingaben per Maus und Toucheingabe können jedoch bei Bedarf von Ihrer App unterstützt werden.
  • Wenn das Zeichnen mit Toucheingaben unterstützt wird, empfehlen wir die Verwendung des Symbols "ED5F" aus der Schriftart "Segoe MLD2 Assets" für die Umschaltfläche mit einem Tooltip "Schreiben per Toucheingabe".

XAML

  1. Zunächst deklarieren wir ein InkToolbarCustomToggleButton-Element (toggleButton) mit einem Click-Ereignislistener, der den Ereignishandler (Toggle_Custom) angibt.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <StackPanel Grid.Row="0" 
                x:Name="HeaderPanel" 
                Orientation="Horizontal">
        <TextBlock x:Name="Header" 
                   Text="Basic ink sample" 
                   Style="{ThemeResource HeaderTextBlockStyle}" 
                   Margin="10" />
    </StackPanel>

    <ScrollViewer Grid.Row="1" 
                  HorizontalScrollBarVisibility="Auto" 
                  VerticalScrollBarVisibility="Auto">
        
        <Grid HorizontalAlignment="Left" VerticalAlignment="Top">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            
            <InkToolbar Grid.Row="0" 
                        Margin="10"
                        x:Name="inkToolbar" 
                        VerticalAlignment="Top"
                        TargetInkCanvas="{x:Bind inkCanvas}">
                <InkToolbarCustomToggleButton 
                x:Name="toggleButton" 
                Click="CustomToggle_Click" 
                ToolTipService.ToolTip="Touch Writing">
                    <SymbolIcon Symbol="{x:Bind TouchWritingIcon}"/>
                </InkToolbarCustomToggleButton>
            </InkToolbar>
            
            <ScrollViewer Grid.Row="1" 
                          Height="500"
                          Width="500"
                          x:Name="scrollViewer" 
                          ZoomMode="Enabled" 
                          MinZoomFactor=".1" 
                          VerticalScrollMode="Enabled" 
                          VerticalScrollBarVisibility="Auto" 
                          HorizontalScrollMode="Enabled" 
                          HorizontalScrollBarVisibility="Auto">
                
                <Grid x:Name="outputGrid" 
                      Height="1000"
                      Width="1000"
                      Background="{ThemeResource SystemControlBackgroundChromeWhiteBrush}">
                    <InkCanvas x:Name="inkCanvas"/>
                </Grid>
                
            </ScrollViewer>
        </Grid>
    </ScrollViewer>
</Grid>

CodeBehind

  1. Im vorherigen Codeausschnitt haben wir einen Click-Ereignislistener und -Handler (Toggle_Custom) auf der benutzerdefinierten Umschaltfläche für die Toucheingabe (ToggleButton) deklariert. Dieser Handler schaltet einfach die Unterstützung für CoreInputDeviceTypes.Touch über die InputDeviceTypes-Eigenschaft des InkPresenter um.

    Außerdem wurde ein Symbol für die Schaltfläche mit dem SymbolIcon-Element und der {x:Bind}-Markuperweiterung angegeben, die es an ein Feld bindet, das in der CodeBehind-Datei (TouchWritingIcon) definiert ist.

    Der folgende Codeausschnitt enthält sowohl den Click-Ereignishandler als auch die Definition von TouchWritingIcon.

namespace Ink_Basic_InkToolbar
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage_AddCustomToggle : Page
    {
        Symbol TouchWritingIcon = (Symbol)0xED5F;

        public MainPage_AddCustomToggle()
        {
            this.InitializeComponent();
        }

        // Handler for the custom toggle button that enables touch inking.
        private void CustomToggle_Click(object sender, RoutedEventArgs e)
        {
            if (toggleButton.IsChecked == true)
            {
                inkCanvas.InkPresenter.InputDeviceTypes |= CoreInputDeviceTypes.Touch;
            }
            else
            {
                inkCanvas.InkPresenter.InputDeviceTypes &= ~CoreInputDeviceTypes.Touch;
            }
        }
    }
}

Benutzerdefiniertes Tool

Sie können eine benutzerdefinierte Schaltfläche erstellen, um ein Nicht-Stift-Werkzeug aufzurufen, das von Ihrer App definiert wird.

Standardmäßig verarbeitet ein InkPresenter alle Eingaben als Freihandstrich oder als Löschstrich. Dazu gehören Eingaben, die durch eine sekundäre Hardware-Funktion beeinflusst wurden, wie zum Beispiel eine Stifttaste, eine rechte Maustaste oder Ähnliches. InkPresenter kann jedoch so konfiguriert werden, dass bestimmte Eingaben unverarbeitet bleiben, die dann zur benutzerdefinierten Verarbeitung an Ihre App übergeben werden können.

In diesem Beispiel definieren wir eine benutzerdefinierte Werkzeugschaltfläche, die bei Auswahl alle nachfolgenden Striche verarbeitet und als Auswahl-Lasso (gestrichelte Linie) anstelle von Tinte gerendert wird. Alle Tintenstriche innerhalb der Grenzen des Auswahlbereichs werden auf Ausgewählt festgelegt.

Hinweis

Siehe Digitalink-Steuerelemente für sowohl die InkCanvas- als auch die InkToolbar-UX-Richtlinien. Die folgende Empfehlung ist für dieses Beispiel relevant:

  • Wenn Strichauswahl bereitgestellt wird, empfehlen wir die Verwendung des Symbols "EF20" aus der Schriftart "Segoe MLD2 Assets" für die Toolschaltfläche mit einer QuickInfo "Auswahltool".

XAML

  1. Zunächst deklarieren wir ein InkToolbarCustomToolButton-Element (customToolButton) mit einem Click-Ereignis-Listener, der den Ereignishandler (customToolButton_Click) angibt, in dem die Strichauswahl konfiguriert ist. (Wir haben auch eine Reihe von Schaltflächen zum Kopieren, Ausschneiden und Einfügen der Strichauswahl hinzugefügt.)

  2. Außerdem fügen wir ein Canvas-Element zum Zeichnen unseres Auswahlstrichs hinzu. Durch die Verwendung einer separaten Ebene zum Zeichnen des Auswahlstrichs wird sichergestellt, dass der InkCanvas-Inhalt unverändert bleibt.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <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>
    <StackPanel x:Name="ToolPanel" Orientation="Horizontal" Grid.Row="1">
        <InkToolbar x:Name="inkToolbar" 
                    VerticalAlignment="Top" 
                    TargetInkCanvas="{x:Bind inkCanvas}">
            <InkToolbarCustomToolButton 
                x:Name="customToolButton" 
                Click="customToolButton_Click" 
                ToolTipService.ToolTip="Selection tool">
                <SymbolIcon Symbol="{x:Bind SelectIcon}"/>
            </InkToolbarCustomToolButton>
        </InkToolbar>
        <Button x:Name="cutButton" 
                Content="Cut" 
                Click="cutButton_Click"
                Width="100"
                Margin="5,0,0,0"/>
        <Button x:Name="copyButton" 
                Content="Copy"  
                Click="copyButton_Click"
                Width="100"
                Margin="5,0,0,0"/>
        <Button x:Name="pasteButton" 
                Content="Paste"  
                Click="pasteButton_Click"
                Width="100"
                Margin="5,0,0,0"/>
    </StackPanel>
    <Grid Grid.Row="2" x:Name="outputGrid" 
              Background="{ThemeResource SystemControlBackgroundChromeWhiteBrush}" 
              Height="Auto">
        <!-- Canvas for displaying selection UI. -->
        <Canvas x:Name="selectionCanvas"/>
        <!-- Canvas for displaying ink. -->
        <InkCanvas x:Name="inkCanvas" />
    </Grid>
</Grid>

CodeBehind

  1. Anschließend behandeln wir das Click-Ereignis für das InkToolbarCustomToolButton in der MainPage.xaml.cs Code-Behind-Datei.

    Mit diesem Handler wird der InkPresenter so konfiguriert, dass nicht verarbeitete Eingaben an die App übergeben werden.

    Ausführlichere Schritte in diesem Code finden Sie in der Pass-Through-Eingabe für die erweiterte Verarbeitung von Stiftinteraktionen und Windows Ink in Windows-Apps.

    Außerdem haben wir ein Symbol für die Schaltfläche mit dem SymbolIcon-Element und der {x:Bind}-Markuperweiterung angegeben, die es an ein Feld bindet, das in der CodeBehind-Datei (SelectIcon) definiert ist.

    Der folgende Codeausschnitt enthält sowohl den Click-Ereignishandler als auch die Definition von SelectIcon.

namespace Ink_Basic_InkToolbar
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage_AddCustomTool : Page
    {
        // Icon for custom selection tool button.
        Symbol SelectIcon = (Symbol)0xEF20;

        // Stroke selection tool.
        private Polyline lasso;
        // Stroke selection area.
        private Rect boundingRect;

        public MainPage_AddCustomTool()
        {
            this.InitializeComponent();

            // Listen for new ink or erase strokes to clean up selection UI.
            inkCanvas.InkPresenter.StrokeInput.StrokeStarted +=
                StrokeInput_StrokeStarted;
            inkCanvas.InkPresenter.StrokesErased +=
                InkPresenter_StrokesErased;
        }

        private void customToolButton_Click(object sender, RoutedEventArgs e)
        {
            // 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;
        }

        // 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();
        }

        private void cutButton_Click(object sender, RoutedEventArgs e)
        {
            inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
            inkCanvas.InkPresenter.StrokeContainer.DeleteSelected();
            ClearSelection();
        }

        private void copyButton_Click(object sender, RoutedEventArgs e)
        {
            inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
        }

        private void pasteButton_Click(object sender, RoutedEventArgs e)
        {
            if (inkCanvas.InkPresenter.StrokeContainer.CanPasteFromClipboard())
            {
                inkCanvas.InkPresenter.StrokeContainer.PasteFromClipboard(
                    new Point(0, 0));
            }
            else
            {
                // Cannot paste from clipboard.
            }
        }

        // Clean up selection UI.
        private void ClearSelection()
        {
            var strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
            foreach (var stroke in strokes)
            {
                stroke.Selected = false;
            }
            ClearBoundingRect();
        }

        private void ClearBoundingRect()
        {
            if (selectionCanvas.Children.Any())
            {
                selectionCanvas.Children.Clear();
                boundingRect = Rect.Empty;
            }
        }

        // 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();
        }

        // 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);
            }
        }
    }
}

Benutzerdefiniertes Freihandrendering

Standardmäßig werden Stifteingaben in einem Hintergrundthread mit niedriger Latenz verarbeitet und beim Zeichnen in Echtzeit "nass" gerendert. Wenn der Strich abgeschlossen ist (indem der Stift oder Finger angehoben oder die Maustaste losgelassen wird), wird der Strich im UI-Thread verarbeitet und "trocken" auf der InkCanvas-Ebene gerendert, die sich oberhalb des Anwendungsinhalts befindet und die nasse Freihandeingabe ersetzt.

Mit der Tintenkontrollplattform können Sie dieses Verhalten außer Kraft setzen und die Tinteingabe vollständig anpassen, indem Sie die Tinteingaben benutzerdefiniert trocknen.

Weitere Informationen zum benutzerdefinierten Trocknen finden Sie unter Stiftinteraktionen und Windows Ink in Windows-Apps.

Hinweis

Benutzerdefinierte Trocknung und die InkToolbar
Wenn Ihre App das standardmäßige Freihandrenderingverhalten des InkPresenter mit einer benutzerdefinierten Trocknungsimplementierung außer Kraft setzt, sind die gerenderten Freihandstriche nicht mehr für die InkToolbar verfügbar, und die integrierten Radierbefehle der InkToolbar funktionieren nicht wie erwartet. Zur Bereitstellung von Radierfunktionen müssen Sie sämtliche Zeigerereignisse behandeln, eine Trefferprüfung für jeden Strich durchführen und den integrierten Befehl „Alle Freihandstriche löschen“ außer Kraft setzen.

Themenbeispiele

Weitere Beispiele