Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Windows-Apps, die Windows Ink unterstützen, können Freihandstriche in eine ISF-Datei (Ink Serialized Format) serialisieren und deserialisieren. Die ISF-Datei ist ein GIF-Bild und enthält zusätzliche Metadaten zu allen Freihandstrich-Eigenschaften und -Verhalten. Apps, die nicht freihandfähig sind, können das statische GIF-Bild anzeigen, einschließlich Alphakanal-Hintergrundtransparenz.
Hinweis
ISF ist die kompakteste persistente Darstellung von Tinte. Sie kann in ein Binärdokumentformat eingebettet werden, z. B. eine GIF-Datei, oder direkt auf die Zwischenablage gelegt werden.
Die Ink Serialized Format (ISF)-Spezifikation kann vom Microsoft Download Centerheruntergeladen werden.
Wichtige APIs: InkCanvas, Windows.UI.Input.Inking
Speichere Freihandstriche in einer Datei
Hier veranschaulichen wir, wie Freihandstriche, die auf einem InkCanvas-Steuerelement gezeichnet werden, gespeichert werden können.
Laden Sie dieses Beispiel aus Speichern und Laden von Freihandstrichen aus einer ISF-Datei (Ink Serialized Format)
Zunächst richten wir die Benutzeroberfläche ein.
Die Benutzeroberfläche enthält die Schaltflächen "Speichern", "Laden" und "Leeren" sowie die InkCanvas.
<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 store sample"
Style="{ThemeResource HeaderTextBlockStyle}"
Margin="10,0,0,0" />
<Button x:Name="btnSave"
Content="Save"
Margin="50,0,10,0"/>
<Button x:Name="btnLoad"
Content="Load"
Margin="50,0,10,0"/>
<Button x:Name="btnClear"
Content="Clear"
Margin="50,0,10,0"/>
</StackPanel>
<Grid Grid.Row="1">
<InkCanvas x:Name="inkCanvas" />
</Grid>
</Grid>
Anschließend legen wir einige grundlegende Eingabeverhalten für Tinte fest.
Die InkPresenter- ist so konfiguriert, dass Eingabedaten von Stift und Maus als Striche (InputDeviceTypes) interpretiert werden, und Listener für die Klickereignisse der Schaltflächen sind deklariert.
public MainPage()
{
this.InitializeComponent();
// Set supported inking device types.
inkCanvas.InkPresenter.InputDeviceTypes =
Windows.UI.Core.CoreInputDeviceTypes.Mouse |
Windows.UI.Core.CoreInputDeviceTypes.Pen;
// Listen for button click to initiate save.
btnSave.Click += btnSave_Click;
// Listen for button click to initiate load.
btnLoad.Click += btnLoad_Click;
// Listen for button click to clear ink canvas.
btnClear.Click += btnClear_Click;
}
Schließlich speichern wir die Freihandeingabe im Klick-Ereignishandler der Schaltfläche Speichern.
Mit einem FileSavePicker- kann der Benutzer sowohl die Datei als auch den Speicherort auswählen, an dem die Tinten-Daten gespeichert werden.
Sobald eine Datei ausgewählt ist, öffnen wir einen IRandomAccessStream Stream, der auf ReadWrite-festgelegt ist.
Anschließend rufen wir SaveAsync- auf, um die Freihandstriche zu serialisieren, die vom InkStrokeContainer- in den Stream verwaltet werden.
// Save ink data to a file.
private async void btnSave_Click(object sender, RoutedEventArgs e)
{
// Get all strokes on the InkCanvas.
IReadOnlyList<InkStroke> currentStrokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
// Strokes present on ink canvas.
if (currentStrokes.Count > 0)
{
// Let users choose their ink file using a file picker.
// Initialize the picker.
Windows.Storage.Pickers.FileSavePicker savePicker =
new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
savePicker.FileTypeChoices.Add(
"GIF with embedded ISF",
new List<string>() { ".gif" });
savePicker.DefaultFileExtension = ".gif";
savePicker.SuggestedFileName = "InkSample";
// Show the file picker.
Windows.Storage.StorageFile file =
await savePicker.PickSaveFileAsync();
// When chosen, picker returns a reference to the selected file.
if (file != null)
{
// Prevent updates to the file until updates are
// finalized with call to CompleteUpdatesAsync.
Windows.Storage.CachedFileManager.DeferUpdates(file);
// Open a file stream for writing.
IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
// Write the ink strokes to the output stream.
using (IOutputStream outputStream = stream.GetOutputStreamAt(0))
{
await inkCanvas.InkPresenter.StrokeContainer.SaveAsync(outputStream);
await outputStream.FlushAsync();
}
stream.Dispose();
// Finalize write so other apps can update file.
Windows.Storage.Provider.FileUpdateStatus status =
await Windows.Storage.CachedFileManager.CompleteUpdatesAsync(file);
if (status == Windows.Storage.Provider.FileUpdateStatus.Complete)
{
// File saved.
}
else
{
// File couldn't be saved.
}
}
// User selects Cancel and picker returns null.
else
{
// Operation cancelled.
}
}
}
Hinweis
GIF ist das einzige Dateiformat, das zum Speichern von Tintendaten unterstützt wird. Die LoadAsync--Methode (im nächsten Abschnitt veranschaulicht) unterstützt jedoch zusätzliche Formate für die Abwärtskompatibilität.
Tintenschläge aus einer Datei laden
Hier demonstrieren wir, wie Freihandzeichnungen aus einer Datei geladen und auf einem InkCanvas-Steuerelement gerendert werden.
Laden Sie dieses Beispiel aus Speichern und Laden von Freihandstrichen aus einer ISF-Datei (Ink Serialized Format)
Zunächst richten wir die Benutzeroberfläche ein.
Die Benutzeroberfläche enthält die Schaltflächen "Speichern", "Laden" und "Leeren" sowie die InkCanvas.
<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 store sample"
Style="{ThemeResource HeaderTextBlockStyle}"
Margin="10,0,0,0" />
<Button x:Name="btnSave"
Content="Save"
Margin="50,0,10,0"/>
<Button x:Name="btnLoad"
Content="Load"
Margin="50,0,10,0"/>
<Button x:Name="btnClear"
Content="Clear"
Margin="50,0,10,0"/>
</StackPanel>
<Grid Grid.Row="1">
<InkCanvas x:Name="inkCanvas" />
</Grid>
</Grid>
Anschließend legen wir einige grundlegende Eingabeverhalten für Tinte fest.
Die InkPresenter- ist so konfiguriert, dass Eingabedaten von Stift und Maus als Striche (InputDeviceTypes) interpretiert werden, und Listener für die Klickereignisse der Schaltflächen sind deklariert.
public MainPage()
{
this.InitializeComponent();
// Set supported inking device types.
inkCanvas.InkPresenter.InputDeviceTypes =
Windows.UI.Core.CoreInputDeviceTypes.Mouse |
Windows.UI.Core.CoreInputDeviceTypes.Pen;
// Listen for button click to initiate save.
btnSave.Click += btnSave_Click;
// Listen for button click to initiate load.
btnLoad.Click += btnLoad_Click;
// Listen for button click to clear ink canvas.
btnClear.Click += btnClear_Click;
}
Schließlich laden wir die Tinte im Klickereignishandler der Schaltfläche Laden.
Ein FileOpenPicker- ermöglicht es dem Benutzer, sowohl die Datei als auch den Speicherort auszuwählen, an dem die gespeicherten Freihanddaten abgerufen werden sollen.
Nachdem eine Datei ausgewählt wurde, öffnen wir einen IRandomAccessStream Datenstrom, der auf Readfestgelegt ist.
Anschließend rufen wir LoadAsync auf, um die gespeicherten Freihandstriche zu lesen, deserialisieren und in den InkStrokeContainerzu laden. Das Laden der Striche in den InkStrokeContainer- bewirkt, dass die InkPresenter- sie sofort in den InkCanvas-rendert.
Hinweis
Alle vorhandenen Striche im InkStrokeContainer werden gelöscht, bevor neue Striche geladen werden.
// Load ink data from a file.
private async void btnLoad_Click(object sender, RoutedEventArgs e)
{
// Let users choose their ink file using a file picker.
// Initialize the picker.
Windows.Storage.Pickers.FileOpenPicker openPicker =
new Windows.Storage.Pickers.FileOpenPicker();
openPicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
openPicker.FileTypeFilter.Add(".gif");
// Show the file picker.
Windows.Storage.StorageFile file = await openPicker.PickSingleFileAsync();
// User selects a file and picker returns a reference to the selected file.
if (file != null)
{
// Open a file stream for reading.
IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
// Read from file.
using (var inputStream = stream.GetInputStreamAt(0))
{
await inkCanvas.InkPresenter.StrokeContainer.LoadAsync(inputStream);
}
stream.Dispose();
}
// User selects Cancel and picker returns null.
else
{
// Operation cancelled.
}
}
Hinweis
GIF ist das einzige Dateiformat, das zum Speichern von Tintendaten unterstützt wird. Die LoadAsync Methode unterstützt jedoch die folgenden Formate für die Abwärtskompatibilität.
Format | BESCHREIBUNG |
---|---|
InkSerializedFormat | Gibt Tinte an, die mithilfe von ISF gespeichert wird. Dies ist die kompakteste beständige Darstellung von Tinte. Sie kann in ein binäres Dokumentformat eingebettet oder direkt in die Zwischenablage eingefügt werden. |
Base64InkSerializedFormat | Gibt Tintenstriche an, die beibehalten werden, indem der ISF als Base64-Datenstrom codiert und gespeichert wird. Dieses Format wird bereitgestellt, damit Tinte direkt in einer XML- oder HTML-Datei kodiert werden kann. |
GIF | Gibt Tinte an, die durch die Verwendung einer GIF-Datei beibehalten wird, die ISF als eingebaute Metadaten enthält. Dadurch können Freihandeingaben in Anwendungen angezeigt werden, die nicht freihandfähig sind, und die volle Freihandtreue beibehalten, wenn sie zu einer freihandfähigen Anwendung zurückkehrt. Dieses Format eignet sich ideal für den Transport von Inhalten in einer HTML-Datei und zur Verwendung durch Freihand- und Nicht-Freihandanwendungen. |
Base64Gif | Gibt Tinte an, die mithilfe einer base64-codierten, verstärkten GIF beibehalten wird. Dieses Format wird bereitgestellt, wenn Tinte direkt in einer XML- oder HTML-Datei codiert werden soll, um später in ein Bild zu konvertieren. Eine mögliche Verwendung davon ist in einem XML-Format, das erstellt wird, um alle Tinteninformationen zu enthalten und verwendet wird, um über Extensible Stylesheet Language Transformations (XSLT) HTML zu generieren. |
Tintenstriche mit der Zwischenablage kopieren und einfügen
Hier wird veranschaulicht, wie die Zwischenablage zum Übertragen von Freihandstrichen zwischen Apps verwendet wird.
Um die Funktionalität der Zwischenablage zu unterstützen, müssen die integrierten InkStrokeContainer- Ausschneiden und Kopieren von Befehlen mindestens einen Freihandstrich ausgewählt werden.
In diesem Beispiel aktivieren wir die Strichauswahl, wenn die Eingabe mit einer Zeichenstift-Drucktaste (oder einer rechten Maustaste) geändert wird. Ein vollständiges Beispiel zur Implementierung der Strichauswahl finden Sie unter "Durchleitungs-Eingabe für erweiterte Verarbeitung" in Stift- und Touch-Interaktionen.
Laden Sie dieses Beispiel herunter von Speichern und Laden von Freihandstrichen aus der Zwischenablage
Zunächst richten wir die Benutzeroberfläche ein.
Die Benutzeroberfläche enthält die Schaltflächen "Ausschneiden", "Kopieren", "Einfügen" und "Löschen" zusammen mit dem InkCanvas und einem Auswahlbereich.
<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="tbHeader"
Text="Basic ink store sample"
Style="{ThemeResource HeaderTextBlockStyle}"
Margin="10,0,0,0" />
<Button x:Name="btnCut"
Content="Cut"
Margin="20,0,10,0"/>
<Button x:Name="btnCopy"
Content="Copy"
Margin="20,0,10,0"/>
<Button x:Name="btnPaste"
Content="Paste"
Margin="20,0,10,0"/>
<Button x:Name="btnClear"
Content="Clear"
Margin="20,0,10,0"/>
</StackPanel>
<Grid x:Name="gridCanvas" Grid.Row="1">
<!-- Canvas for displaying selection UI. -->
<Canvas x:Name="selectionCanvas"/>
<!-- Inking area -->
<InkCanvas x:Name="inkCanvas"/>
</Grid>
</Grid>
Anschließend legen wir einige grundlegende Eingabeverhalten für Tinte fest.
Die InkPresenter- ist so konfiguriert, dass Eingabedaten von Stift und Maus als Tintenstriche interpretiert werden (InputDeviceTypes). Listener für die Mausklickereignisse auf den Schaltflächen sowie Zeiger- und Strichereignisse für die Auswahlfunktion werden hier ebenfalls deklariert.
Ein vollständiges Beispiel zur Implementierung der Strichauswahl finden Sie unter "Durchleitungs-Eingabe für erweiterte Verarbeitung" in Stift- und Touch-Interaktionen.
public MainPage()
{
this.InitializeComponent();
// Set supported inking device types.
inkCanvas.InkPresenter.InputDeviceTypes =
Windows.UI.Core.CoreInputDeviceTypes.Mouse |
Windows.UI.Core.CoreInputDeviceTypes.Pen;
// Listen for button click to cut ink strokes.
btnCut.Click += btnCut_Click;
// Listen for button click to copy ink strokes.
btnCopy.Click += btnCopy_Click;
// Listen for button click to paste ink strokes.
btnPaste.Click += btnPaste_Click;
// Listen for button click to clear ink canvas.
btnClear.Click += btnClear_Click;
// By default, the InkPresenter processes input modified by
// a secondary affordance (pen barrel button, right mouse
// button, or similar) as ink.
// To pass through modified input to the app for custom processing
// on the app UI thread instead of the background ink thread, set
// InputProcessingConfiguration.RightDragAction to LeaveUnprocessed.
inkCanvas.InkPresenter.InputProcessingConfiguration.RightDragAction =
InkInputRightDragAction.LeaveUnprocessed;
// Listen for unprocessed pointer events from modified input.
// The input is used to provide selection functionality.
inkCanvas.InkPresenter.UnprocessedInput.PointerPressed +=
UnprocessedInput_PointerPressed;
inkCanvas.InkPresenter.UnprocessedInput.PointerMoved +=
UnprocessedInput_PointerMoved;
inkCanvas.InkPresenter.UnprocessedInput.PointerReleased +=
UnprocessedInput_PointerReleased;
// Listen for new ink or erase strokes to clean up selection UI.
inkCanvas.InkPresenter.StrokeInput.StrokeStarted +=
StrokeInput_StrokeStarted;
inkCanvas.InkPresenter.StrokesErased +=
InkPresenter_StrokesErased;
}
Nach dem Hinzufügen der Strichauswahlunterstützung implementieren wir die Zwischenablagefunktionalität in den Klickereignishandlern der Schaltflächen Ausschneiden, Kopierenund Einfügen.
Zum Ausschneiden rufen wir zuerst CopySelectedToClipboard- für die InkStrokeContainer- des InkPresenter-auf.
Anschließend rufen wir DeleteSelected auf, um die Striche von der Zeichenfläche zu löschen.
Schließlich löschen wir alle Auswahlstriche aus dem Auswahlbereich.
private void btnCut_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
inkCanvas.InkPresenter.StrokeContainer.DeleteSelected();
ClearSelection();
}
// Clean up selection UI.
private void ClearSelection()
{
var strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
foreach (var stroke in strokes)
{
stroke.Selected = false;
}
ClearDrawnBoundingRect();
}
private void ClearDrawnBoundingRect()
{
if (selectionCanvas.Children.Any())
{
selectionCanvas.Children.Clear();
boundingRect = Rect.Empty;
}
}
Zum Kopieren rufen wir einfach CopySelectedToClipboard im InkStrokeContainer des InkPresenterauf.
private void btnCopy_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
}
Zum Einfügen prüfen wir mit CanPasteFromClipboard, ob der Inhalt der Zwischenablage auf die Leinwand eingefügt werden kann.
In diesem Fall rufen wir PasteFromClipboard auf, um die Freihandstriche in die InkStrokeContainer des InkPresentereinzufügen, wodurch dann die Striche im Freihandbereich gerendert werden.
private void btnPaste_Click(object sender, RoutedEventArgs e)
{
if (inkCanvas.InkPresenter.StrokeContainer.CanPasteFromClipboard())
{
inkCanvas.InkPresenter.StrokeContainer.PasteFromClipboard(
new Point(0, 0));
}
else
{
// Cannot paste from clipboard.
}
}
Verwandte Artikel
Themenbeispiele
- Speichern und Laden von Tintenstrichen aus einer Ink Serialized Format (ISF) Datei
- Speichern und Laden von Freihandstrichen aus der Zwischenablage
Andere Beispiele
Windows developer