Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Aplikacje systemu Windows, które obsługują Windows Ink, mogą serializować i deserializować pociągnięcia piórem do pliku Ink Serialized Format (ISF). Plik ISF jest obrazem GIF z dodatkowymi metadanymi dla wszystkich właściwości i zachowań pociągnięć atramentu. Aplikacje, które nie obsługują funkcji pisma cyfrowego, mogą wyświetlać statyczny obrazek GIF, w tym przezroczystość tła z kanałem alfa.
Uwaga / Notatka
ISF to najbardziej kompaktowa trwała reprezentacja atramentu. Można go osadzić w formacie dokumentu binarnego, takim jak plik GIF, lub umieścić bezpośrednio w Schowku.
Specyfikację formatu serializowanego pisma odkowego (ISF) można pobrać z Centrum pobierania Microsoft.
Ważne interfejsy API: InkCanvas, Windows.UI.Input.Inking
Zapisywanie pociągnięć tuszem do pliku
W tym miejscu demonstrujemy, jak zapisać pociągnięcia atramentu rysowane na kontrolce InkCanvas.
Najpierw skonfigurujemy interfejs użytkownika.
Interfejs użytkownika zawiera przyciski "Zapisz", "Załaduj" i "Wyczyść" oraz 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>
Następnie ustawiamy niektóre podstawowe zachowania danych wejściowych atramentu.
InkPresenter jest skonfigurowany do interpretowania danych wejściowych zarówno z pióra, jak i myszy jako pociągnięć atramentu (InputDeviceTypes), a odbiorniki zdarzeń kliknięcia przycisków są deklarowane.
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;
}
Na koniec zapiszemy atrament w procedurze obsługi zdarzeń kliknięcia przycisku Zapisz .
FileSavePicker pozwala użytkownikowi wybrać zarówno plik, jak i lokalizację, w której zapisywane są dane atramentu.
Po wybraniu pliku otworzymy strumień IRandomAccessStream ustawiony na ReadWrite.
Następnie wywołujemy SaveAsync, aby serializować pociągnięcia atramentem zarządzane przez InkStrokeContainer do strumienia.
// 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.
}
}
}
Uwaga / Notatka
Plik GIF jest jedynym formatem pliku obsługiwanym do zapisywania danych pisma odkowego. Jednak metoda LoadAsync (pokazana w następnej sekcji) obsługuje dodatkowe formaty zgodności z poprzednimi wersjami.
Ładowanie pociągnięć atramentowych z pliku
W tym miejscu pokazano, jak ładować pociągnięcia pisma odręcznego z pliku i renderować je na kontrolce InkCanvas .
Pobierz ten przykład z Zapisywanie i ładowanie pociągnięć atramentu z pliku w formacie Ink Serialized Format (ISF)
Najpierw skonfigurujemy interfejs użytkownika.
Interfejs użytkownika zawiera przyciski "Zapisz", "Załaduj" i "Wyczyść" oraz 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>
Następnie ustawiamy niektóre podstawowe zachowania danych wejściowych atramentu.
InkPresenter jest skonfigurowany do interpretowania danych wejściowych zarówno z pióra, jak i z myszy jako pociągnięć atramentu (InputDeviceTypes), a odbiorniki zdarzeń kliknięcia na przyciskach zostały zadeklarowane.
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;
}
Na koniec ładujemy tusz w obsłudze zdarzenia kliknięcia przycisku Załaduj.
Funkcja FileOpenPicker umożliwia użytkownikowi wybranie zarówno pliku, jak i lokalizacji, z której mają zostać pobrane zapisane dane pisma odręcznego.
Po wybraniu pliku otworzymy strumień IRandomAccessStream ustawiony na Odczyt.
Następnie wywołamy metodę LoadAsync, aby odczytać, deserializować i załadować zapisane pociągnięcia atramentu do InkStrokeContainer. Ładowanie pociągnięć do InkStrokeContainer powoduje, że InkPresenter natychmiast renderuje je na InkCanvas.
Uwaga / Notatka
Wszystkie istniejące pociągnięcia w InkStrokeContainer są czyszczone przed załadowaniem nowych pociągnięć.
// 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.
}
}
Uwaga / Notatka
Plik GIF jest jedynym formatem obsługiwanym do zapisywania danych atramentu. Jednak metoda LoadAsync obsługuje następujące formaty w celu zapewnienia zgodności z poprzednimi wersjami.
| Format | Description |
|---|---|
| InkSerializedFormat | Określa atrament, który jest utrwalany z wykorzystaniem ISF. Jest to najbardziej kompaktowa trwała reprezentacja tuszu. Można ją osadzić w formacie dokumentu binarnego lub umieścić bezpośrednio w Schowku. |
| Base64InkSerializedFormat | Określa atrament, który jest utrwalany przez kodowanie isF jako strumienia base64. Ten format jest dostarczany, dzięki czemu atrament może być zakodowany bezpośrednio w pliku XML lub HTML. |
| GIF | Określa atrament, który jest utrwalany przy użyciu pliku GIF, który zawiera isF jako metadane osadzone w pliku. Dzięki temu atrament można wyświetlać w aplikacjach, które nie obsługują atramentu, i zachować pełną wierność atramentu po powrocie do aplikacji obsługującej atrament. Format ten jest idealny do transportowania zawartości atramentu w pliku HTML i umożliwia jego użycie w aplikacjach wykorzystujących atrament i tych, które go nie wykorzystują. |
| Base64Gif | Określa atrament, który jest utrwalany przy użyciu zakodowanego w formacie base64 wzmocnionego pliku GIF. Ten format jest udostępniany, gdy atrament ma być zakodowany bezpośrednio w pliku XML lub HTML w celu późniejszej konwersji na obraz. Możliwe zastosowanie tego elementu to format XML wygenerowany w celu przechowywania wszystkich informacji o tuszu i służący do generowania HTML za pomocą rozszerzalnego języka transformacji arkuszy stylów (XSLT). |
Kopiuj i wklejaj pociągnięcia tuszu za pomocą schowka
W tym miejscu pokazano, jak używać schowka do przesyłania pociągnięć pióra między aplikacjami.
Aby obsługiwać funkcjonalność schowka, polecenia wycinania i kopiowania dostępne we wbudowanym kontenerze InkStrokeContainer wymagają wybrania co najmniej jednego pociągnięcia atramentu.
W tym przykładzie włączamy selekcję pociągnięcia, gdy przyciskiem pióra (lub prawym przyciskiem myszy) modyfikowane są dane wejściowe. Pełny przykład implementacji zaznaczenia pociągnięcia można znaleźć w temacie Wprowadzanie przekazywane na potrzeby zaawansowanego przetwarzania w interakcjach pióra i rysika.
Pobierz ten przykład z Zapisywanie i ładowanie pociągnięć atramentem ze schowka
Najpierw skonfigurujemy interfejs użytkownika.
Interfejs użytkownika zawiera przyciski "Cut", "Copy", "Paste" i "Clear", a także InkCanvas oraz kanwę wyboru.
<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>
Następnie ustawiamy niektóre podstawowe zachowania danych wejściowych atramentu.
InkPresenter jest skonfigurowany do interpretowania danych wejściowych zarówno z pióra, jak i myszy jako pociągnięć od atramentu (InputDeviceTypes). Odbiorniki zdarzeń kliknięcia na przyciskach, a także zdarzenia wskaźnika i pociągnięcia dla funkcji wyboru są również deklarowane tutaj.
Pełny przykład implementacji wyboru pociągnięcia można znaleźć w temacie Wejście przekazywane do zaawansowanego przetwarzania w interakcjach pióra i rysika.
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;
}
Na koniec, po dodaniu obsługi wyboru pociągnięcia, implementujemy funkcje schowka w obsłudze zdarzeń kliknięcia przycisków Wytnij, Kopiuj i Wklej.
Dla operacji wycięcia najpierw wywołujemy CopySelectedToClipboard na InkStrokeContainer w InkPresenter.
Następnie wywołujemy polecenie DeleteSelected, aby usunąć pociągnięcia z płótna pisma odręcznego.
Na koniec usuwamy wszystkie linie zaznaczenia z kanwy zaznaczenia.
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;
}
}
W celu kopiowania po prostu wywołujemy CopySelectedToClipboard na InkStrokeContainerInkPresenter.
private void btnCopy_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
}
W przypadku wklejania wywołujemy funkcję CanPasteFromClipboard, aby zapewnić, że zawartość schowka może być wklejona na płótno atramentu.
Jeśli tak, wywołamy funkcję PasteFromClipboard, aby wstawić pociągnięcia pisma odręcznego ze schowka do InkStrokeContainer w InkPresenterze, który następnie renderuje pociągnięcia na płótno pisma odręcznego.
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.
}
}
Powiązane artykuły
Przykłady tematów
- Zapisywanie i ładowanie ruchów tuszem z pliku ISF (Ink Serialized Format)
- Zapisywanie i ładowanie pociągnięć piórem ze schowka
Inne przykłady
Windows developer