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 mit zusätzlichen Metadaten für alle Freihandstricheigenschaften und -verhalten. Apps, die nicht freihandfähig sind, können das statische GIF-Bild anzeigen, einschließlich Alphakanal-Hintergrundtransparenz.
Hinweis
ISF ist die kompakteste beständige Tintendarstellung. Sie kann in ein Binärdokumentformat eingebettet werden, z. B. eine GIF-Datei, oder direkt auf der Zwischenablage.
Die Spezifikation für serialisiertes Freihandformat (Ink Serialized Format, ISF) kann aus dem Microsoft Download Center heruntergeladen werden.
Wichtige APIs: InkCanvas, Windows.UI.Input.Inking
Speichern von Freihandstrichen in einer Datei
Hier wird veranschaulicht, wie Freihandstriche gespeichert werden, die auf einem InkCanvas-Steuerelement gezeichnet werden.
Laden Sie dieses Beispiel von Speichern und Laden von Freihandstrichen aus einer ISF-Datei (Ink Serialized Format) herunter.
Zunächst richten wir die Benutzeroberfläche ein.
Die Benutzeroberfläche enthält die Schaltflächen "Speichern", "Laden" und "Löschen" und " 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 Tinteingabeverhalten fest.
Der InkPresenter ist so konfiguriert, dass er Eingabedaten von Stift und Maus als Freihandstriche (InputDeviceTypes) interpretiert, und die Listener für Klickevents auf den Schaltflächen werden 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".
Ein FileSavePicker ermöglicht es dem Benutzer, sowohl die Datei als auch den Speicherort auszuwählen, an dem die digitalen Ink-Daten gespeichert werden.
Sobald eine Datei ausgewählt ist, öffnen wir einen IRandomAccessStream-Datenstrom , der auf ReadWrite festgelegt ist.
Anschließend rufen wir SaveAsync auf, um die vom InkStrokeContainer verwalteten Freihandstriche in den Datenstrom zu serialisieren.
// 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.
Laden von Freihandstrichen aus einer Datei
Hier zeigen wir, wie Freihandstriche aus einer Datei geladen und in einem InkCanvas-Steuerelement gerendert werden.
Laden Sie dieses Beispiel von "Speichern und Laden von Freihandstrichen aus einer ISF-Datei (Ink Serialized Format)" herunter.
Zunächst richten wir die Benutzeroberfläche ein.
Die Benutzeroberfläche enthält die Schaltflächen "Speichern", "Laden" und "Löschen" und " 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.
Der InkPresenter ist so konfiguriert, dass Eingabedaten von Stift und Maus als Freihandstriche (InputDeviceTypes) interpretiert werden. Zudem werden Listener für die Klickereignisse auf die Schaltflächen 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 Klick-Ereignishandler der Schaltfläche "Laden".
Ein FileOpenPicker ermöglicht es dem Benutzer, sowohl die Datei als auch den Speicherort für den Abruf der gespeicherten Tinten-Daten auszuwählen.
Sobald eine Datei ausgewählt wurde, öffnen wir einen IRandomAccessStream-Datenstrom , der auf "Lesen" festgelegt ist.
Anschließend rufen wir LoadAsync auf, um die gespeicherten Freihandstriche zu lesen, zu de-serialisieren und in den InkStrokeContainer zu laden. Durch das Laden der Striche in den InkStrokeContainer veranlasst, dass der InkPresenter sie sofort auf 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 Freihanddaten unterstützt wird. Die LoadAsync-Methode unterstützt jedoch die folgenden Formate für die Abwärtskompatibilität.
| Format | Description |
|---|---|
| InkSerializedFormat | Gibt Tinten an, die mithilfe von ISF gespeichert werden. Dies ist die kompakteste persistente Darstellung von Tinte. Sie kann in ein binäres Dokumentformat eingebettet oder direkt in die Zwischenablage eingefügt werden. |
| Base64InkSerializedFormat | Spezifiziert Tinte, die persistiert wird, indem der ISF als Base64-Datenstrom codiert wird. Dieses Format wird bereitgestellt, damit Tinte direkt in einer XML- oder HTML-Datei codiert werden kann. |
| GIF | Gibt Tinte an, die mit einer GIF-Datei gespeichert wird, die ISF als eingebettete Metadaten in der Datei enthält. Dadurch können Tintenanwendungen in Programmen angezeigt werden, die nicht tintfähig sind, und ihre volle Tintentrestnlität beibehalten, wenn sie zu einer tintfähigen Anwendung zurückkehren. Dieses Format eignet sich ideal, um Tinteninhalte innerhalb einer HTML-Datei zu transportieren und für Anwendungen mit oder ohne Tintenunterstützung nutzbar zu machen. |
| Base64Gif | Gibt digitale Zeichnungen an, die mithilfe einer base64-codierten, erweiterten GIF-Datei gespeichert werden. Dieses Format wird bereitgestellt, wenn Tintenstriche direkt in einer XML- oder HTML-Datei codiert platziert werden sollen, um später in ein Bild zu konvertieren. Eine mögliche Anwendung besteht darin, ein XML-Format zu erstellen, das alle Tinteninformationen enthält und über Extensible Stylesheet Language Transformations (XSLT) zur Generierung von HTML verwendet wird. |
Kopieren und Einfügen von Freihandstrichen mit der Zwischenablage
Hier wird veranschaulicht, wie die Zwischenablage zum Übertragen von Freihandstrichen zwischen Apps verwendet wird.
Zur Unterstützung der Zwischenablagefunktion müssen für die integrierten Ausschneiden- und Kopierbefehle des InkStrokeContainer mindestens ein oder mehrere Freihandstriche 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 für die Implementierung der Strichauswahl finden Sie unter "Durchgangseingabe für die erweiterte Verarbeitung" in Zeichen- und Stifteingabe-Interaktionen.
Laden Sie dieses Beispiel aus Speichern und Laden von Freihandstrichen aus der Zwischenablage herunter.
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.
Der InkPresenter ist so konfiguriert, dass Eingabedaten von Stift und Maus als Freihandstriche (InputDeviceTypes) interpretiert werden. Listener für die Klickereignisse auf den Schaltflächen sowie Zeiger- und Strichereignisse für die Auswahlfunktionalität werden hier ebenfalls deklariert.
Ein vollständiges Beispiel für die Implementierung der Strichauswahl finden Sie unter Pass-Through-Eingabe für die erweiterte Verarbeitung in Zeichen- und Eingabestiftinteraktionen.
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", "Kopieren" und "Einfügen" .
Zum Ausschneiden rufen wir zuerst CopySelectedToClipboard im InkStrokeContainer des InkPresenter auf.
Anschließend rufen wir DeleteSelected auf, um die Striche aus dem Freihandzeichenbereich zu entfernen.
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 auf dem InkStrokeContainer des InkPresenter auf.
private void btnCopy_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
}
Zum Einfügen rufen wir CanPasteFromClipboard auf, um sicherzustellen, dass der Inhalt in der Zwischenablage in die Zeichenfläche eingefügt werden kann.
In diesem Fall rufen wir PasteFromClipboard auf, um die Freihandstriche der Zwischenablage in den InkStrokeContainer des InkPresenter einzufügen, wodurch die Striche dann auf der Zeichenfläche 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 Freihandstrichen aus einer ISF-Datei (Ink Serialized Format)
- Speichern und Laden von Freihandstrichen aus der Zwischenablage
Weitere Beispiele
Windows developer