Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Приложения Windows, поддерживающие Windows Ink, могут сериализовать и десериализовать росчерки в файл ISF. Файл ISF — это GIF-изображение, содержащее дополнительные метаданные для всех свойств и поведения штрихов рукописного ввода. Приложения, которые не поддерживают рукописный ввод, могут просматривать статическое GIF-изображение, включая прозрачный фон альфа-канала.
Замечание
ISF — это самое компактное постоянное представление рукописного ввода. Он может быть внедрен в двоичный формат документа, например GIF-файл или помещен непосредственно в буфер обмена.
Спецификация сериализованного формата рукописного ввода (ISF) можно скачать из Центра загрузки Майкрософт.
Важные API: InkCanvas, Windows.UI.Input.Inking
Сохранение росчерков рукописного ввода в файл
Здесь мы покажем, как сохранить чернильные штрихи, нарисованные на элементе управления InkCanvas.
Скачайте этот пример из «Сохранение и загрузка чернил из файлов Ink Serialized Format (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.
Скачайте этот пример из «Сохранение и загрузка чернил из файлов Ink Serialized Format (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;
}
Наконец, мы загружаем чернила в обработчик событий нажатия кнопки Load.
Объект FileOpenPicker позволяет пользователю выбрать файл и расположение, откуда следует извлечь сохраненные данные рукописного ввода.
После выбора файла мы открываем поток IRandomAccessStream, установленный для чтения.
Затем мы вызываем 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 поддерживает следующие форматы для обратной совместимости.
| Формат | Описание |
|---|---|
| InkSerializedFormat | Указывает чернила, сохраняемые посредством ISF. Это самое компактное устойчивое представление цифровых чернил. Его можно внедрить в двоичный формат документа или поместить непосредственно в буфер обмена. |
| Base64InkSerializedFormat | Указывает чернила, которые сохраняются посредством кодирования ISF в поток base64. Этот формат предоставляется для кодирования чернил непосредственно в XML-файле или HTML-файле. |
| Гиф | Указывает чернила, которые сохраняются с использованием 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 на InkStrokeContainerInkPresenter.
private void btnCopy_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
}
Для вставки вызовите CanPasteFromClipboard, чтобы убедиться, что содержимое в буфере обмена можно вставить на полотно для рукописных данных.
В этом случае мы вызываем PasteFromClipboard для вставки росчерков рукописного ввода буфера обмена в InkStrokeContainerInkPresenter, который затем отрисовывает росчерки на холсте рукописного ввода.
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)
- Сохранение и загрузка штрихов из буфера обмена
Другие примеры
- Простой чернильный пример (C#/C++)
- Комплексный пример использования чернил (C++)
- пример Ink (JavaScript)
- Get Started Tutorial: поддержка рукописного ввода в приложении Windows
- пример раскраски Coloring book sample
- Пример заметок для семьи