Хранение и извлечение данных движения пера Windows Ink
Приложения Windows, поддерживающие Windows Ink, могут сериализовать и десериализировать росчерки рукописного ввода в файл сериализованного формата рукописного ввода (ISF). ФАЙЛ ISF — это GIF-изображение с дополнительными метаданными для всех свойств и поведения росчерка рукописного ввода. Приложения, которые не включены в рукописный ввод, могут просматривать статический GIF-образ, включая прозрачность фона альфа-канала.
Примечание.
ISF — это самое компактное постоянное представление рукописного ввода. Он может быть внедрен в двоичный формат документа, например GIF-файл или помещен непосредственно в буфер обмена.
Спецификация сериализованного формата рукописного ввода (ISF) можно скачать из Центра загрузки Майкрософт.
Важные API: InkCanvas, Windows.UI.Input.Inking
Сохранение росчерков рукописного ввода в файл
Здесь мы покажем, как сохранить росчерки рукописного ввода, нарисованные на элементе управления InkCanvas.
Скачайте этот пример из файла сохранения и загрузки росчерков рукописного ввода из файла сериализованного формата рукописного ввода (ISF)
Сначала мы настраиваем пользовательский интерфейс.
Пользовательский интерфейс включает кнопки "Сохранить", "Загрузить" и "Очистить" и 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>
Затем мы задали некоторые базовые функции ввода рукописного ввода.
InkPresenter настроен для интерпретации входных данных как пера, так и мыши в виде росчерков рукописного ввода (InputDeviceTypes), а прослушиватели для событий нажатия кнопки объявляются.
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;
}
Наконец, мы сохраняем рукописный ввод в обработчике событий нажатия кнопки "Сохранить ".
FileSavePicker позволяет пользователю выбрать как файл, так и расположение, в котором сохраняются данные рукописного ввода.
После выбора файла мы открываем поток IRandomAccessStream с значением ReadWrite.
Затем мы вызываем SaveAsync для сериализации росчерков рукописного ввода, управляемых inkStrokeContainer в поток.
// 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.
}
}
}
Примечание.
GIF — это единственный формат файла, поддерживаемый для сохранения данных рукописного ввода. Однако метод LoadAsync (показан в следующем разделе) поддерживает дополнительные форматы для обратной совместимости.
Загрузка росчерков рукописного ввода из файла
Здесь мы покажем, как загружать росчерки рукописного ввода из файла и отображать их на элементе управления InkCanvas .
Скачайте этот пример из файла сохранения и загрузки росчерков рукописного ввода из файла сериализованного формата рукописного ввода (ISF)
Сначала мы настраиваем пользовательский интерфейс.
Пользовательский интерфейс включает кнопки "Сохранить", "Загрузить" и "Очистить" и 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>
Затем мы задали некоторые базовые функции ввода рукописного ввода.
InkPresenter настроен для интерпретации входных данных как пера, так и мыши в виде росчерков рукописного ввода (InputDeviceTypes), а прослушиватели для событий нажатия кнопки объявляются.
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;
}
Наконец, мы загружаем рукописный ввод в обработчик событий нажатия кнопки "Загрузка ".
FileOpenPicker позволяет пользователю выбрать как файл, так и расположение, откуда получить сохраненные данные рукописного ввода.
После выбора файла мы открываем поток IRandomAccessStream с значением Read.
Затем мы вызываем LoadAsync для чтения, десериализации и загрузки сохраненных росчерков рукописного ввода в inkStrokeContainer. Загрузка штрихов в InkStrokeContainer приводит к тому, что InkPresenter немедленно отрисовывает их в InkCanvas.
Примечание.
Все существующие штрихи в InkStrokeContainer очищаются до загрузки новых штрихов.
// 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.
}
}
Примечание.
GIF — это единственный формат файла, поддерживаемый для сохранения данных рукописного ввода. Однако метод LoadAsync поддерживает следующие форматы для обратной совместимости.
Формат | Description |
---|---|
InkSerializedFormat | Указывает рукописный ввод, сохраняемый с помощью ISF. Это самое компактное постоянное представление рукописного ввода. Его можно внедрить в двоичный формат документа или поместить непосредственно в буфер обмена. |
Base64InkSerializedFormat | Указывает рукописный ввод, который сохраняется путем кодирования ISF в виде потока base64. Этот формат предоставляется таким образом, чтобы рукописный ввод можно кодировать непосредственно в XML-файле или HTML-файле. |
Gif | Указывает рукописный ввод, который сохраняется с помощью GIF-файла, содержащего ISF в качестве метаданных, внедренных в файл. Это позволяет просматривать рукописные данные в приложениях, которые не включены рукописным вводом и поддерживают полную точность рукописного ввода при возвращении в приложение с поддержкой рукописного ввода. Этот формат идеально подходит при транспортировке рукописного содержимого в HTML-файле и для использования рукописными и не рукописными приложениями. |
Base64Gif | Указывает рукописный ввод, который сохраняется с помощью защищенного GIF в кодировке Base64. Этот формат предоставляется при кодировании рукописного ввода непосредственно в XML-файле или HTML-файле для последующего преобразования в изображение. Это можно использовать в формате XML, созданном для хранения всех данных рукописного ввода и используемых для создания HTML через расширяемые преобразования языка стилей (XSLT). |
Копирование и вставка росчерков рукописного ввода с помощью буфера обмена
Здесь мы покажем, как использовать буфер обмена для передачи росчерков рукописного ввода между приложениями.
Для поддержки функций буфера обмена встроенные команды выреза и копирования InkStrokeContainer требуют выбора одного или нескольких росчерков рукописного ввода.
В этом примере мы включаем выделение штрихов при изменении входных данных с помощью кнопки заключичного пера (или правой кнопки мыши). Полный пример реализации выделения штрихов см. в разделе "Сквозные входные данные" для расширенной обработки в взаимодействиях пера и пера.
Скачайте этот пример из "Сохранить и загрузить рукописные росчерки" из буфера обмена
Сначала мы настраиваем пользовательский интерфейс.
Пользовательский интерфейс включает кнопки "Вырезать", "Копировать", "Вставить" и "Очистить", а также кнопки 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="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>
Затем мы задали некоторые базовые функции ввода рукописного ввода.
InkPresenter настраивается для интерпретации входных данных из пера и мыши в виде росчерков рукописного ввода (InputDeviceTypes). Прослушиватели событий щелчка на кнопках, а также события указателя и штриха для функций выбора также объявляются здесь.
Полный пример реализации выделения штрихов см. в разделе "Сквозные входные данные" для расширенной обработки в взаимодействиях пера и пера.
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;
}
Наконец, после добавления поддержки выделения штрихов мы реализуем функциональные возможности буфера обмена в обработчиках событий щелчка кнопок "Вырезать", "Копировать" и "Вставить ".
Для вырезания сначала вызывается CopySelectedToClipboard в InkStrokeContainer inkPresenter.
Затем мы вызываем DeleteSelected , чтобы удалить штрихи из рукописного холста.
Наконец, мы удаляем все штрихи выделения на холсте выбора.
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;
}
}
Для копирования мы просто вызываем CopySelectedToClipboard в InkStrokeContainer inkPresenter.
private void btnCopy_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
}
Для вставки вызовите CanPasteFromClipboard , чтобы убедиться, что содержимое в буфере обмена можно вставлять на холст рукописного ввода.
В этом случае мы вызываем InsertFromClipboard, чтобы вставить росчерки рукописного ввода буфера обмена в inkStrokeContainer inkPresenter, который затем отрисовывает штрихи на холст рукописного ввода.
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.
}
}
Связанные статьи
Примеры раздела
- Сохранение и загрузка росчерков рукописного ввода из файла сериализованного формата рукописного ввода (ISF)
- Сохранение и загрузка росчерков рукописного ввода из буфера обмена
Другие примеры
Windows developer