Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Приложения 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;
}
Наконец, мы загружаем чернила в обработчик событий нажатия кнопки 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 на InkStrokeContainerInkPresenter.
Затем мы вызываем 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, чтобы вставить рукописные штрихи из буфера обмена в 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