Freigeben über


Hinzufügen eines InkToolbar-Elements zu einer Windows-App

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

Das Steuerelement InkCanvas ermöglicht grundlegende Windows Ink-Funktionen. Verwenden Sie es zum Wiedergeben der Stifteingabe entweder als Freihandstrich (unter Verwendung der Standardeinstellungen für Farbe und Dicke) oder als Radierstrich.

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

Als vollständig transparente Überlagerung verfügt das InkCanvas nicht über eine integrierte Benutzeroberfläche zum Festlegen der Eigenschaften von Freihandstrichen. Wenn die standardmäßige Freihandeingabefunktion geändert werden soll, Benutzer die Möglichkeit haben sollen, die Eigenschaften von Freihandstrichen festzulegen, und andere benutzerdefinierte Freihandfunktionen unterstützt werden sollen, haben Sie zwei Optionen:

  • Verwenden Sie im CodeBehind das zugrunde liegende InkPresenter-Objekt, das an den InkCanvas angebunden ist.

    Die InkPresenter-APIs unterstützen umfangreiche Anpassungen der Freihandeingabe. Weitere Informationen finden Sie unter Zeichen- und Eingabestiftinteraktionen in Windows-Apps.

  • Binden Sie eine InkToolbar an den InkCanvas an. Standardmäßig verfügt die InkToolbar über eine anpassbare und erweiterbare Sammlung von Schaltflächen zum Aktivieren von Freihandfunktionen wie Strichgröße, Freihandfarbe und Stiftspitze.

    Wir besprechen die InkToolbar in diesem Thema.

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

Standard-InkToolbar

Die InToolbar enthält standardmäßig Schaltflächen zum Zeichnen, Löschen, Hervorheben sowie zum Anzeigen eines Schablone (Lineal oder Winkelmesser). 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 Freihand-App eine Standard-InkToolbar hinzufügen möchten, müssen Sie sie einfach auf derselben Seite wie Ihr InkCanvas platzieren und die beiden Steuerelemente zuordnen.

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

Hinweis

Stellen Sie sicher, dass die InkToolbar nach dem InkCanvas deklariert wird. Wenn nicht, wird die InkToolbar durch die InkCanvas-Überlagerung 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 Anpassungen

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

Angeben von Position und Ausrichtung

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

XAML

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

Standard Explizit
Standardspeicherort und -ausrichtung der Freihandsymbolleiste Explizite Freihandsymbolleistenposition und -ausrichtung
Standardposition und Ausrichtung der Windows Ink-Symbolleiste Explizite Position und Ausrichtung der Windows Ink-Symbolleiste

Hier sehen Sie den 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 manchen Fällen möchten Sie die Position und Ausrichtung der Freihandsymbolleiste vielleicht basierend auf der Benutzereinstellung oder dem Gerätestatus festlegen. Das folgende Beispiel veranschaulicht das Festlegen von Position und Ausrichtung der Freihandsymbolleiste basierend auf den Einstellungen für das Schreiben mit der rechten oder linken Hand über Einstellungen > Geräte > Stift und Windows Ink > Stift > Wählen Sie aus, mit welcher Hand Sie schreiben.

Einstellen der dominanten Hand
Einstellen der dominanten Hand

Sie können diese Einstellung über die Eigenschaft HandPreference von Windows.UI.ViewManagement abfragen und HorizontalAlignment basierend auf dem zurückgegebenen Wert festlegen. In diesem Beispiel positionieren wir 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.

Laden Sie dieses Beispiel aus Position und Ausrichtung der Freihandsymbolleiste (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

Anhand der Bindung können Sie auch nach Benutzeroberflächen-Updates basierend auf Änderungen an Benutzereinstellungen, Geräteeinstellungen oder Gerätestatus suchen. Im folgenden Beispiel erweitern wir das vorherige Beispiel und zeigen die dynamische Positionierung der Freihandsymbolleiste basierend auf der Geräteausrichtung mithilfe von Bindung, einem ViewMOdel-Objekt und der INotifyPropertyChanged-Schnittstelle.

Laden Sie dieses Beispiel aus Position und Ausrichtung der Freihandsymbolleiste (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 mit dem Namen InkToolbarSnippetHostViewModel.cs).

      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 zur Datei hinzu.

    4. Fügen Sie eine statische Membervariable namens Instance und eine statische schreibgeschützte Eigenschaft namens Instance hinzu. Machen Sie das 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 zum Benachrichtigen von Clients, in der Regel angebundenen Clients, dient, dass ein Eigenschaftswert geändert wurde. Wir verwenden dies zum Behandeln von Änderungen an der Geräteausrichtung (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 Boolesche Eigenschaften hinzu: LeftHandedLayout (gleiche Funktionalität wie im vorherigen reinen XAML-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 mit dem Namen HorizontalAlignmentFromHandednessConverter.cs und VerticalAlignmentFromAppViewConverter.cs).

    3. Fügen Sie zu jeder Datei die Namespaces using Windows.UI.Xaml und using Windows.UI.Xaml.Data 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 auf der rechten Seite der App für rechtshändige Benutzer und auf der linken Seite der App für linkshändige Benutzer.
      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 Freihandsymbolleiste in der Mitte der App für hochformatige Ausrichtung und oben in der App für querformatige Ausrichtung (soll die Benutzerfreundlichkeit verbessern und ist nur 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 jetzt die Datei MainPage.xaml.cs.

    1. Fügen Sie using using locationandorientation.ViewModels zur Liste der Namespaces hinzu, um unser ViewModel zuzuordnen.
    2. Fügen Sie using Windows.UI.ViewManagement zur 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 dann die Datei MainPage.xaml.cs.

    1. Fügen Sie xmlns:converters="using:locationandorientation.Converters" zum Page-Element zum Binden an unsere Konverter hinzu.

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

      <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 Datei „InkToolbarSnippetHostViewModel.cs“ zurück, um der Klasse InkToolbarSnippetHostViewModel unsere Booleschen Eigenschaften PortraitLayout und LeftHandedLayout hinzuzufügen, zusammen mit der Unterstützung für die Neuanbindung PortraitLayout, wenn sich dieser Eigenschaftswert ä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 Freihand-App verfügen, die sich sowohl an die dominante Handpräferenz des Benutzers anpasst als auch dynamisch auf die Ausrichtung des Geräts des Benutzers 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 das integrierte InkToolbarPencilButton-Objekt 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 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.

Das kann über XAML oder Code geschehen.

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 in 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 in 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 Freihandfunktionen

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

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.

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

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

Hinweis: 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 Stiftspitzen-Eigenschaften wie Form, Drehung und Größe definieren.

Benutzerdefinierte kalligrafische Stiftschaltfläche
Benutzerdefinierte kalligrafische Stiftschaltfläche

In diesem Beispiel definieren wir einen benutzerdefinierten Stift mit einer breiten Spitze, die einfache kalligrafische 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 nennen Sie sie CalligraphicPen.cs.
  3. Ersetzen Sie in Calligraphic.cs den standardmäßigen verwendeten 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 lokales Seitenressourcenverzeichnis, das einen Verweis auf den benutzerdefinierten Stift (CalligraphicPen) erstellt, der in CalligraphicPen.cs definiert ist, und eine Pinselsammlung, 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 eine InkToolbar 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 ein- oder auszuschalten. Wenn sie aktiviert ist, funktioniert das Feature in Verbindung mit dem aktiven Tool.

In diesem Beispiel definieren wir eine benutzerdefinierte Umschaltfläche, die Freihandeingaben per Toucheingabe ermöglicht (standardmäßig ist die Toucheingabe nicht aktiviert).

Hinweis

Wenn Sie Freihandeingaben per Toucheingabe unterstützen müssen, wird empfohlen, die sie mithilfe eines CustomToggleButton mit dem in diesem Beispiel angegebenen Symbol und der QuickInfo zu aktivieren.

In der Regel wird die Toucheingabe für die direkte Manipulation eines Objekts oder der App-UI verwendet. Um die Unterschiede beim Aktivieren der Freihandeingabe zu veranschaulichen, platzieren wir den InkCanvas in einem ScrollViewer-Container und legen die Abmessungen des ScrollViewers auf kleiner als InkCanvas fest.

Wenn die App gestartet wird, wird nur die Freihandeingabe unterstützt, und die Toucheingabe wird verwendet, um die Freihandoberfläche zu verschieben oder zu zoomen. Wenn die Toucheingabe aktiviert ist, kann die Freihandoberfläche nicht über die Toucheingabe verschoben oder vergrößert werden.

Hinweis

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

  • Sie genießen die InkToolbar und die Freihand-Eingabe im Allgemeinen am besten mit einem aktiven Stift. Freihandeingaben per Maus und Toucheingabe können jedoch bei Bedarf von Ihrer App unterstützt werden.
  • Bei Unterstützung der Freihandfunktion per Toucheingabe wird empfohlen, das Symbol „ED5F“ aus der Schriftart „Segoe MLD2 Assets“ für die Umschaltfläche mit einer QuickInfo „Schreiben durch Berühren“ zu verwenden.

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 Toolschaltfläche erstellen, um ein Nicht-Stift-Tool aufzurufen, das von Ihrer App definiert wird.

Standardmäßig verarbeitet ein InkPresenter alle Eingaben als Freihandstrich oder als Radierstrich. Dazu gehören Eingaben, die von einer sekundären Hardware geändert wurden, z. B. eine Stift-Drucktaste, 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 Toolschaltfläche, die bei Auswahl nachfolgende Striche verarbeitet und als Auswahl-Lasso (gestrichelte Linie) anstelle von Freihand wiedergegeben wird. Alle Freihandstriche innerhalb der Grenzen des Auswahlbereichs werden auf Ausgewählt festgelegt.

Hinweis

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

  • Für die Bereitstellung der Strichauswahl wird empfohlen, das Symbol „EF20“ aus der Schriftart „Segoe MLD2 Assets“ für die Toolschaltfläche mit einer QuickInfo „Auswahlwerkzeug“ zu verwenden.

XAML

  1. Zunächst deklarieren wir ein InkToolbarCustomToolButton-Element (customToolButton) mit einem Click-Ereignislistener, 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 und dessen Inhalt unverändert bleiben.

<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 InkToolbarCustomToolButton in der CodeBehind-Datei MainPage.xaml.cs.

    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 Passthrough-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 Rendern von Freihandeingaben

Standardmäßig werden Freihandeingaben in einem Hintergrundthread mit geringer Latenz verarbeitet und beim Zeichnen „nass“ gerendert. Wenn der Strich abgeschlossen ist (Stift oder Finger angehoben oder Maustaste losgelassen), wird der Strich im UI-Thread verarbeitet und auf der InkCanvas-Ebene (oberhalb des Anwendungsinhalts und als Ersatz für die nasse Freihandeingabe) „trocken“ gerendert.

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

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

Hinweis

Benutzerdefiniertes Trocknen 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 alle Zeigerereignisse behandeln, Treffertests für jeden Strich durchführen und den integrierten Befehl „Freihand löschen“ außer Kraft setzen.

Themenbeispiele

Weitere Beispiele