Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Surface Pen (доступно для покупки в магазине Microsoft Store).
Обзор
Оптимизируйте приложение Windows для ввода пера, чтобы обеспечить как стандартную функциональность указательных устройств, так и наилучший опыт использования Windows Ink для ваших пользователей.
Замечание
В этом разделе рассматривается платформа Windows Ink. Общие сведения об обработке входных данных указателя (аналогично мыши, касания и сенсорной панели), см. в разделе "Обработка ввода указателя".
Платформа Windows Ink, вместе с устройством пера, предоставляет естественный способ создания цифровых рукописных заметок, рисунков и аннотаций. Платформа поддерживает запись входных данных дигитайзера в виде рукописных данных, создания рукописных данных, управления данными рукописного ввода, отрисовки рукописных данных в виде росчерков рукописного ввода на выходном устройстве и преобразования рукописного ввода в текст с помощью распознавания рукописного ввода.
Помимо записи базовой позиции и перемещения пера, когда пользователь пишет или рисует, ваше приложение также может отслеживать и собирать различные уровни давления, используемого на протяжении штриха. Эта информация, а также настройки формы наконечника пера, размера и угла наклона, цвета чернил и назначения (обычный ввод, стирание, выделение и выбор), позволяют предоставлять пользователям впечатления, которые очень похожи на письмо или рисование на бумаге с помощью пера, карандаша или кисти.
Замечание
Ваше приложение также может поддерживать ввод рукописного ввода с других устройств на основе указателя, включая сенсорные дигитайзеры и устройства мыши.
Платформа цифрового чернила очень гибкая. Он предназначен для поддержки различных уровней функциональности в зависимости от ваших требований.
Руководство по Windows Ink UX см. раздел Inking controls.
Компоненты платформы Windows Ink
| Компонент | Описание |
|---|---|
| InkCanvas | Элемент управления платформой пользовательского интерфейса XAML, который по умолчанию получает и отображает все входные данные из пера в виде росчерка рукописного ввода или штриха удаления. Дополнительные сведения об использовании InkCanvas см. в разделах Распознавание штрихов Windows Ink как текста и Хранение и получение данных штрихов Windows Ink. |
| InkPresenter | Объект code-behind, созданный вместе с элементом управления InkCanvas (доступный через свойство InkCanvas.InkPresenter). Этот объект предоставляет все функции рукописного ввода по умолчанию, предоставляемые InkCanvas, а также комплексный набор API для дополнительной настройки и персонализации. Дополнительные сведения об использовании InkPresenter см. в разделах Распознавание рукописных вводов Windows Ink как текста и Сохранение и извлечение данных о рукописных вводах Windows Ink. |
| InkToolbar | Элемент управления платформы пользовательского интерфейса XAML, содержащий настраиваемую и расширяемую коллекцию кнопок, которые активируют функции, связанные с рукописным вводом, в связанном InkCanvas. Дополнительные сведения об использовании InkToolbar см. в разделе Добавление InkToolbar в приложение Windows для рукописного ввода. |
| IInkD2DRenderer | Позволяет отрисовывать росчерки рукописного ввода в указанном контексте устройства Direct2D универсального приложения Windows, а не в элементе управления по умолчанию InkCanvas. Это обеспечивает полную настройку интерфейса рукописного ввода. Дополнительные сведения см. в примере Комплексная чернильная проба. |
Основы цифрового инкования на InkCanvas
Чтобы добавить основные функции рукописного ввода, просто поместите элемент управления для платформы InkCanvas на соответствующую страницу в приложении.
По умолчанию InkCanvas поддерживает рукописный ввод только при помощи пера. Входные данные отображаются либо в виде росчерка рукописного ввода с использованием параметров по умолчанию для цвета и толщины (черной шариковой ручки толщиной 2 пикселя), либо обрабатываются как ластик (если входные данные из наконечника ластика или кончик пера изменены кнопкой стирания).
Замечание
Если подсказка или кнопка ластика отсутствует, можно настроить InkCanvas для обработки входных данных из кончика пера в виде штриха удаления.
В этом примере InkCanvas накладывает фоновое изображение.
Замечание
InkCanvas имеет свойства Height и Width по умолчанию равны нулю, если он не является дочерним элементом того, который автоматически размеряет дочерние элементы, например, такие элементы управления, как StackPanel или Grid.
<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 sample"
Style="{ThemeResource HeaderTextBlockStyle}"
Margin="10,0,0,0" />
</StackPanel>
<Grid Grid.Row="1">
<Image Source="Assets\StoreLogo.png" />
<InkCanvas x:Name="inkCanvas" />
</Grid>
</Grid>
В этой серии изображений показано, как отрисовывается ввод пера этим элементом управления InkCanvas.
|
|
|
|---|---|---|
| Пустой InkCanvas с фоновым изображением. | InkCanvas с мазками чернил. | Объект InkCanvas с одним штрихом, который был удален (обратите внимание, что удаление действует на весь штрих, а не на часть). |
Функции рукописного ввода, поддерживаемые элементом управления InkCanvas, предоставляются объектом code-behind с именем InkPresenter.
Для простого рукописного ввода вам не нужно беспокоиться о InkPresenter. Однако для настройки и конфигурирования поведения рукописного ввода в InkCanvas необходимо получить доступ к соответствующему объекту InkPresenter.
Базовая настройка с помощью InkPresenter
Объект InkPresenter создается с каждым элементом управления InkCanvas.
Замечание
Невозможно напрямую создать экземпляр InkPresenter. Вместо этого доступ осуществляется через свойство InkPresenter элемента InkCanvas.
Наряду с предоставлением всех стандартных функций рукописного ввода, которые соответствуют элементу управления InkCanvas, InkPresenter предлагает полный набор API для дополнительной настройки штрихов и более детального управления входными данными пера (как стандартными, так и измененными). Сюда входят свойства штриха, поддерживаемые типы устройств ввода и то, обрабатываются ли входные данные объектом или передаются в приложение для обработки.
Замечание
Стандартный рукописный ввод (с кончика пера или кнопки ластика) не изменяется с использованием вторичного аппаратного средства, такого как кнопка на корпусе пера, правая кнопка мыши или аналогичное устройство.
По умолчанию поддерживается рукописный ввод только с использованием пера. Здесь мы настраиваем InkPresenter для интерпретации входных данных из пера и мыши в виде росчерков рукописного ввода. Мы также устанавливаем некоторые начальные атрибуты штрихов для отрисовки на InkCanvas.
Чтобы включить ввод мыши и сенсорного ввода, задайте для свойства InputDeviceTypesinkPresenter сочетание значений CoreInputDeviceTypes , которые требуется.
public MainPage()
{
this.InitializeComponent();
// Set supported inking device types.
inkCanvas.InkPresenter.InputDeviceTypes =
Windows.UI.Core.CoreInputDeviceTypes.Mouse |
Windows.UI.Core.CoreInputDeviceTypes.Pen;
// Set initial ink stroke attributes.
InkDrawingAttributes drawingAttributes = new InkDrawingAttributes();
drawingAttributes.Color = Windows.UI.Colors.Black;
drawingAttributes.IgnorePressure = false;
drawingAttributes.FitToCurve = true;
inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes);
}
Атрибуты росчерка рукописного ввода можно задать динамически для удовлетворения требований пользователей или приложений.
Здесь мы позволим пользователю выбрать из списка цветов рукописного ввода.
<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 customization sample"
VerticalAlignment="Center"
Style="{ThemeResource HeaderTextBlockStyle}"
Margin="10,0,0,0" />
<TextBlock Text="Color:"
Style="{StaticResource SubheaderTextBlockStyle}"
VerticalAlignment="Center"
Margin="50,0,10,0"/>
<ComboBox x:Name="PenColor"
VerticalAlignment="Center"
SelectedIndex="0"
SelectionChanged="OnPenColorChanged">
<ComboBoxItem Content="Black"/>
<ComboBoxItem Content="Red"/>
</ComboBox>
</StackPanel>
<Grid Grid.Row="1">
<Image Source="Assets\StoreLogo.png" />
<InkCanvas x:Name="inkCanvas" />
</Grid>
</Grid>
Затем мы обрабатываем изменения выбранного цвета и соответствующим образом обновляем атрибуты штриха.
// Update ink stroke color for new strokes.
private void OnPenColorChanged(object sender, SelectionChangedEventArgs e)
{
if (inkCanvas != null)
{
InkDrawingAttributes drawingAttributes =
inkCanvas.InkPresenter.CopyDefaultDrawingAttributes();
string value = ((ComboBoxItem)PenColor.SelectedItem).Content.ToString();
switch (value)
{
case "Black":
drawingAttributes.Color = Windows.UI.Colors.Black;
break;
case "Red":
drawingAttributes.Color = Windows.UI.Colors.Red;
break;
default:
drawingAttributes.Color = Windows.UI.Colors.Black;
break;
};
inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes);
}
}
На этих изображениях показано, как настраиваются и обрабатываются данные с пера с помощью InkPresenter.
InkCanvas с штрихами чернил по умолчанию.
InkCanvas с красными штрихами, выбранными пользователем.
Чтобы обеспечить функциональность, выходящую за рамки рукописного ввода и стирания, например, выбор штриха, ваше приложение должно учитывать определенные входные данные для InkPresenter, чтобы передавать их необработанными для обработки непосредственно вашим приложением.
Сквозной ввод для расширенной обработки
По умолчанию InkPresenter обрабатывает все вводимые данные как рукописный штрих или стирающий штрих, включая данные, изменённые дополнительным аппаратным средством, например кнопкой на корпусе пера, правой кнопкой мыши или аналогичной. Однако обычно пользователи ожидают некоторые дополнительные функциональные возможности или измененное поведение с этими дополнительными разрешениями.
В некоторых случаях также может потребоваться предоставить дополнительные функции для перьев без дополнительных возможностей (функции, которые обычно не связаны с наконечником пера), для других типов входных устройств или измененного поведения на основе выбора пользователя в пользовательском интерфейсе вашего приложения.
Для поддержки этого можно настроить InkPresenter , чтобы оставить определенные входные данные без обработки. Затем эти необработанные входные данные передаются в приложение для обработки.
Пример – Использование необработанных входных данных для реализации выбора штрихов
Платформа Windows Ink не предоставляет встроенную поддержку действий, требующих модифицированного ввода, таких как выбор штриха. Для поддержки таких функций необходимо предоставить пользовательское решение в приложениях.
В следующем примере кода (весь код находится в файлах MainPage.xaml и MainPage.xaml.cs) показано, как включить выделение штрихов при изменении входных данных с помощью кнопки "корпуса ручки" (или правой кнопки мыши).
Сначала мы настраиваем пользовательский интерфейс в MainPage.xaml.
Здесь мы добавим холст (под InkCanvas) для рисования штриха выделения. Использование отдельного слоя для рисования штриха выделения позволяет не изменять 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="Advanced ink customization sample" VerticalAlignment="Center" Style="{ThemeResource HeaderTextBlockStyle}" Margin="10,0,0,0" /> </StackPanel> <Grid Grid.Row="1"> <!-- Canvas for displaying selection UI. --> <Canvas x:Name="selectionCanvas"/> <!-- Inking area --> <InkCanvas x:Name="inkCanvas"/> </Grid> </Grid>В MainPage.xaml.cs мы объявляем несколько глобальных переменных для хранения ссылок на аспекты пользовательского интерфейса выбора. В частности, штрих выделения лассо и рамка, которая выделяет выбранные штрихи.
// Stroke selection tool. private Polyline lasso; // Stroke selection area. private Rect boundingRect;Затем мы настраиваем InkPresenter для интерпретации входных данных от пера и мыши как рукописные росчерки и задаем начальные атрибуты этих росчерков, используемые для отображения на InkCanvas.
Самое главное, мы используем свойство InputProcessingConfigurationinkPresenter , чтобы указать, что любые измененные входные данные должны обрабатываться приложением. Измененные входные данные задаются путем назначения InputProcessingConfiguration.RightDragAction значением InkInputRightDragAction.LeaveUnprocessed. Если это значение установлено, InkPresenter передает через класс InkUnprocessedInput набор событий указателя для вашей обработки.
Мы назначаем слушателей для необработанных событий PointerPressed, PointerMoved и PointerReleased, передаваемых InkPresenter. Все функции выбора реализованы в обработчиках этих событий.
Наконец, мы назначаем прослушиватели для событий StrokeStarted и StrokesErased элемента InkPresenter. Обработчики этих событий используются для очистки пользовательского интерфейса выбора при запуске нового штриха или удалении существующего штриха.
public MainPage() { this.InitializeComponent(); // Set supported inking device types. inkCanvas.InkPresenter.InputDeviceTypes = Windows.UI.Core.CoreInputDeviceTypes.Mouse | Windows.UI.Core.CoreInputDeviceTypes.Pen; // Set initial ink stroke attributes. InkDrawingAttributes drawingAttributes = new InkDrawingAttributes(); drawingAttributes.Color = Windows.UI.Colors.Black; drawingAttributes.IgnorePressure = false; drawingAttributes.FitToCurve = true; inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes); // 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; }Затем мы определяем обработчики для необработанных событий PointerPressed, PointerMoved и PointerReleased, передаваемых через InkPresenter.
Все функции выбора реализованы в этих обработчиках, включая штрих лассо и ограничивающий прямоугольник.
// Handle unprocessed pointer events from modified input. // The input is used to provide selection functionality. // Selection UI is drawn on a canvas under the InkCanvas. private void UnprocessedInput_PointerPressed( InkUnprocessedInput sender, PointerEventArgs args) { // Initialize a selection lasso. lasso = new Polyline() { Stroke = new SolidColorBrush(Windows.UI.Colors.Blue), StrokeThickness = 1, StrokeDashArray = new DoubleCollection() { 5, 2 }, }; lasso.Points.Add(args.CurrentPoint.RawPosition); selectionCanvas.Children.Add(lasso); } private void UnprocessedInput_PointerMoved( InkUnprocessedInput sender, PointerEventArgs args) { // Add a point to the lasso Polyline object. lasso.Points.Add(args.CurrentPoint.RawPosition); } private void UnprocessedInput_PointerReleased( InkUnprocessedInput sender, PointerEventArgs args) { // Add the final point to the Polyline object and // select strokes within the lasso area. // Draw a bounding box on the selection canvas // around the selected ink strokes. lasso.Points.Add(args.CurrentPoint.RawPosition); boundingRect = inkCanvas.InkPresenter.StrokeContainer.SelectWithPolyLine( lasso.Points); DrawBoundingRect(); }Чтобы завершить обработчик событий PointerReleased, мы очищаем слой выбора всего содержимого (штрих лассо), а затем рисуем один ограничивающий прямоугольник вокруг росчерков рукописного ввода, охватываемых областью лассо.
// Draw a bounding rectangle, on the selection canvas, encompassing // all ink strokes within the lasso area. private void DrawBoundingRect() { // Clear all existing content from the selection canvas. selectionCanvas.Children.Clear(); // Draw a bounding rectangle only if there are ink strokes // within the lasso area. if (!((boundingRect.Width == 0) || (boundingRect.Height == 0) || boundingRect.IsEmpty)) { var rectangle = new Rectangle() { Stroke = new SolidColorBrush(Windows.UI.Colors.Blue), StrokeThickness = 1, StrokeDashArray = new DoubleCollection() { 5, 2 }, Width = boundingRect.Width, Height = boundingRect.Height }; Canvas.SetLeft(rectangle, boundingRect.X); Canvas.SetTop(rectangle, boundingRect.Y); selectionCanvas.Children.Add(rectangle); } }Наконец, мы определим обработчики для событий StrokeStarted иStrokesErased InkPresenter.
Обе эти функции просто вызывают одну и ту же функцию очистки, чтобы всякий раз при обнаружении нового штриха очищать текущий выбор.
// Handle new ink or erase strokes to clean up selection UI. private void StrokeInput_StrokeStarted( InkStrokeInput sender, Windows.UI.Core.PointerEventArgs args) { ClearSelection(); } private void InkPresenter_StrokesErased( InkPresenter sender, InkStrokesErasedEventArgs args) { 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; } }
Настраиваемая отрисовка чернил
По умолчанию входные данные рукописного ввода обрабатываются в фоновом потоке с низкой задержкой и отображаются во время выполнения или "мокрые", как оно нарисовано. После завершения штриха (когда перо или палец поднят, или отпущена кнопка мыши), штрих обрабатывается в потоке пользовательского интерфейса и отображается "сухим" на слой InkCanvas (над содержимым приложения и заменяя влажный рукописный ввод).
Это поведение по умолчанию можно переопределить и полностью контролировать процесс ввода данных пером путем "настраиваемой сушки" мокрых штрихов. Хотя поведение по умолчанию обычно достаточно для большинства приложений, существует несколько случаев, когда может потребоваться настраиваемая сушка, к ним относятся:
- Более эффективное управление большими или сложными коллекциями рукописных росчерков
- Более эффективная поддержка перемещения и масштабирования на больших холстах для рукописного ввода
- Чередование чернил и других объектов, таких как фигуры или текст, при сохранении порядка слоев (z-order)
- Высушивание и преобразование чернил синхронно в фигуру DirectX (например, прямая линия или другая фигура растеризуются и интегрируются в содержимое приложения в отличие от отдельного слоя InkCanvas).
Для настройки пользовательской сушки требуется объект IInkD2DRenderer для управления вводом рукописного ввода и его отрисовки в контексте Direct2D универсального приложения Windows вместо элемента управления InkCanvas.
При вызове ActivateCustomDrying (до загрузки InkCanvas), приложение создает объект InkSynchronizer, чтобы настроить процесс высыхания рукописного штриха для SurfaceImageSource или VirtualSurfaceImageSource.
Оба SurfaceImageSource и VirtualSurfaceImageSource предоставляют общую поверхность DirectX, в которую ваше приложение может рисовать и композировать её в содержимое приложения, хотя VSIS предоставляет виртуальную поверхность, которая больше экрана для эффективного панорамирования и масштабирования. Поскольку визуальные обновления этих поверхностей синхронизированы с потоком пользовательского интерфейса XAML, когда чернила наносятся на любую из этих поверхностей, можно одновременно удалить нарисованный рукописный ввод из InkCanvas.
Вы также можете настроить сухой ввод чернил для SwapChainPanel, но синхронизация с потоком пользовательского интерфейса не гарантируется, и может возникнуть задержка между моментом отрисовки чернил на SwapChainPanel и удалением чернил с InkCanvas.
Полный пример этой функции см. в примере Complex ink.
Замечание
Настраиваемая сушка и панель инструментов для работы с чернилами
Если приложение переопределяет поведение отрисовки рукописного ввода по умолчанию InkPresenter с пользовательской реализацией сушки, отрисованные росчерки рукописного ввода больше не доступны в inkToolbar и встроенные команды очистки InkToolbar не работают должным образом. Чтобы обеспечить функциональность стирания, необходимо обрабатывать все события указателя, выполнять тестирование попаданий на каждом штрихе и переопределять встроенную команду "Стереть все рукописные вводы".
Другие статьи в этом разделе
| Тема | Описание |
|---|---|
| Распознавание росчерков | Преобразование рукописных росчерков в текст с помощью распознавания почерка или в фигуры с использованием настраиваемого распознавания. |
| Хранение и извлечение штрихов рукописного ввода | Храните данные о штрихах рукописного ввода в файле формата GIF, используя встроенные метаданные в формате сериализованного рукописного ввода (ISF). |
| Добавьте панель инструментов InkToolbar в приложение Windows для рукописного ввода | Добавьте панель inkToolbar по умолчанию в приложение Windows рукописного ввода, добавьте настраиваемую кнопку пера в панель InkToolbar и привязите настраиваемую кнопку пера к пользовательскому определению пера. |
Связанные статьи
- Начало работы: поддержка рукописного ввода в приложении Windows
- Обработка входных данных указателя
- Определение устройств ввода
- Спецификация формата сериализации чернил (ISF).
Программные интерфейсы
Образцы
- Get Started Tutorial: поддержка рукописного ввода в приложении Windows
- Простой чернильный пример (C#/C++)
- Комплексный пример использования чернил (C++)
- пример Ink (JavaScript)
- пример раскраски Coloring book sample
- Пример заметок для семьи
- Основной пример ввода
- пример входных данных с низкой задержкой
- Пример режима взаимодействия пользователя
- пример визуальных элементов Focus