Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Это приложение демонстрирует работу с классом RealTimeStylus. Подробный обзор API StylusInput, включая класс RealTimeStylus, см. в разделе Доступ и управление вводом пера. См. сведения о синхронных и асинхронных подключаемых модулях в разделе Подключаемые модули и класс RealTimeStylus.
Обзор примера
Подключаемые модули, объекты, реализующие интерфейс IStylusSyncPlugin или IStylusAsyncPlugin, можно добавить в объект RealTimeStylus. В этом примере приложения используется несколько типов подключаемых модулей:
- Плагин фильтра пакетов: изменяет пакеты. Подключаемый модуль фильтра пакетов в этом примере изменяет сведения о пакете путем ограничения всех данных пакета (x,y) в прямоугольной области.
- Подключаемый модуль настраиваемого динамического рендеринга: изменяет свойства динамической отрисовки. Пользовательский подключаемый модуль динамической отрисовки в этом примере изменяет способ отображения чернил путем рисования небольшого круга вокруг каждой точки (x,y) штриха.
- Подключаемый модуль динамического отрисовщика: изменяет качества динамической отрисовки. В этом примере показано использование объекта DynamicRendererв качестве подключаемого модуля для обработки динамического отображения рукописного ввода.
- Подключаемый модуль распознавателя жестов: распознает жесты приложения. В этом примере показано использование объекта GestureRecognizer в качестве плагина для распознавания жестов приложения (когда он работает на системе, в которой присутствует распознаватель жестов от Майкрософт).
Кроме того, этот пример предоставляет пользовательский интерфейс, позволяющий пользователю добавлять, удалять и изменять порядок каждого подключаемого модуля в коллекции. Пример решения содержит два проекта: RealTimeStylusPluginApp и RealTimeStylusPlugins. RealTimeStylusPluginApp содержит пользовательский интерфейс для примера. RealTimeStylusPlugins содержит реализации подключаемых модулей. Проект RealTimeStylusPlugins определяет пространство имен RealTimeStylusPlugins, содержащее фильтр пакетов и подключаемые модули динамического отрисовщика. Это пространство имен ссылается на проект RealTimeStylusPluginApp. Проект RealTimeStylusPlugins использует Microsoft.Ink, Microsoft.StylusInputи пространства имён Microsoft.StylusInput.PluginData.
Смотрите обзор пространств имен Microsoft.StylusInput и Microsoft.StylusInput.PluginData в архитектуре API StylusInput.
Плагин фильтра пакетов
Подключаемый модуль фильтрации пакетов является синхронным плагином, демонстрирующим модификацию пакета. В частности, он определяет прямоугольник на форме. Все пакеты, нарисованные за пределами области, отображаются внутри области. Класс подключаемого модуля PacketFilterPlugin
регистрируется для уведомления о событиях ввода StylusDown
, StylusUp
и Packets
пером. Класс реализует методы StylusDown, StylusUpи методы Packets, определенные в классе IStylusSyncPlugin.
Общедоступному конструктору для PacketFilterPlugin
требуется структура прямоугольника . Этот прямоугольник определяет прямоугольную область в координатах пространства рукописного ввода (01mm = 1 единица HIMETRIC), в которой будут содержаться пакеты. Прямоугольник хранится в частном поле rectangle
.
public class PacketFilterPlugin:IStylusSyncPlugin
{
private System.Drawing.Rectangle rectangle = System.Drawing.Rectangle.Empty;
public PacketFilterPlugin(Rectangle r)
{
rectangle = r;
}
// ...
Класс PacketFilterPlugin
регистрирует уведомления о событиях путем реализации аксессора get для свойства DataInterest. В этом случае плагин заинтересован в реагировании на уведомления StylusDown
, Packets
, StylusUp
и Error
. Пример возвращает эти значения, как определено в перечислении DataInterestMask. Метод StylusDown вызывается, когда кончик пера касается поверхности дигитайзера. Метод StylusUp вызывается, когда кончик пера покидает поверхность дигитайзера. Метод пакетов вызывается, когда объект RealTimeStylus получает пакеты. Метод ошибки вызывается, когда текущий плагин или предыдущий плагин вызывает исключение.
public DataInterestMask DataInterest
{
get
{
return DataInterestMask.StylusDown |
DataInterestMask.Packets |
DataInterestMask.StylusUp |
DataInterestMask.Error;
}
}
//...
Класс PacketFilterPlugin
обрабатывает большинство этих уведомлений в вспомогательном методе ModifyPacketData
. Метод ModifyPacketData
получает значения x и y для каждого нового пакета из класса PacketsData. Если любое значение находится за пределами прямоугольника, метод заменяет значение ближайшей точкой, которая по-прежнему находится в прямоугольнике. Это пример того, как плагин может заменить данные пакетов в процессе их получения из потока ввода пера.
private void ModifyPacketData(StylusDataBase data)
{
for (int i = 0; i < data.Count ; i += data.PacketPropertyCount)
{
// packet data always has x followed by y followed by the rest
int x = data[i];
int y = data[i+1];
// Constrain points to the input rectangle
x = Math.Max(x, rectangle.Left);
x = Math.Min(x, rectangle.Right);
y = Math.Max(y, rectangle.Top);
y = Math.Min(y, rectangle.Bottom);
// If necessary, modify the x,y packet data
if (x != data[i])
{
data[i] = x;
}
if (y != data[i+1])
{
data[i+1] = y;
}
}
}
Подключаемый модуль пользовательского динамического рендера
Класс CustomDynamicRenderer
также реализует класс IStylusSyncPlugin для получения уведомлений с вводом пера. Затем он обрабатывает уведомление Packets
, чтобы нарисовать небольшой круг вокруг каждой новой точки пакета.
Класс содержит переменную графики, которая содержит ссылку на графический объект, переданный в конструктор класса. Это графический объект, используемый для динамической отрисовки.
private Graphics myGraphics;
public CustomDynamicRendererPlugin(Graphics g)
{
myGraphics = g;
}
//...
Когда подключаемый модуль динамического отрисовщика получает уведомление о пакетах, он извлекает данные (x,y) и рисует небольшой зеленый круг вокруг точки. Это пример кастомной отрисовки на основе потока ввода пером.
public void Packets(RealTimeStylus sender, PacketsData data)
{
for (int i = 0; i < data.Count; i += data.PacketPropertyCount)
{
// Packet data always has x followed by y followed by the rest
Point point = new Point(data[i], data[i+1]);
// Since the packet data is in Ink Space coordinates, we need to convert to Pixels...
point.X = (int)Math.Round((float)point.X * (float)myGraphics.DpiX/2540.0F);
point.Y = (int)Math.Round((float)point.Y * (float)myGraphics.DpiY/2540.0F);
// Draw a circle corresponding to the packet
myGraphics.DrawEllipse(Pens.Green, point.X - 2, point.Y - 2, 4, 4);
}
}
Проект RealTimeStylusPluginApp
Проект RealTimeStylusPluginApp демонстрирует ранее описанные подключаемые модули, а также подключаемые модули GestureRecognizer и DynamicRenderer. Пользовательский интерфейс проекта состоит из:
- Форма, содержащая элемент управления GroupBox, используемый для определения области рукописного ввода.
- Элемент управления CheckedListBox для списка и выбора доступных подключаемых модулей.
- Пара объектов Button для активации повторного упорядочивания плагинов.
Проект определяет структуру, PlugInListItem
, чтобы упростить управление подключаемыми модулями, используемыми в проекте. Структура PlugInListItem
содержит плагин и описание.
Сам класс RealTimeStylusPluginApp
реализует класс IStylusAsyncPlugin. Это необходимо, чтобы класс RealTimeStylusPluginApp
мог быть уведомлён, когда подключаемый модуль GestureRecognizer добавляет данные жестов в выходную очередь. Приложение регистрируется для уведомления о CustomStylusDataAdded. При получении данных жеста RealTimeStylusPluginApp
помещает его описание в строку состояния в нижней части формы.
public void CustomStylusDataAdded(RealTimeStylus sender, CustomStylusData data)
{
if (data.CustomDataId == GestureRecognizer.GestureRecognitionDataGuid)
{
GestureRecognitionData grd = data.Data as GestureRecognitionData;
if (grd != null)
{
if (grd.Count > 0)
{
GestureAlternate ga = grd[0];
sbGesture.Text = "Gesture=" + ga.Id + ", Confidence=" + ga.Confidence;
}
}
}
}
Заметка
В процессе реализации CustomStylusDataAdded интересно отметить, что можно определить данные пользовательского жеста в выходной очереди с помощью GUID (используя поле GestureRecognitionDataGuid) или по типу (используя результат оператора as). В примере используются оба метода идентификации для демонстрационных целей. Любой подход также является допустимым.
В обработчике событий Load Form приложение создает экземпляры классов PacketFilter
и CustomDynamicRenderer
и добавляет их в поле списка. Затем приложение пытается создать экземпляр класса GestureRecognizer, а при успешном выполнении добавляет его в поле списка. Это завершается ошибкой, если распознаватель жестов отсутствует в системе. Затем приложение создает экземпляр объекта DynamicRenderer и добавляет его в поле списка. Наконец, приложение активирует каждый подключаемый модуль и сам объект RealTimeStylus.
Также важно отметить, что в вспомогательных методах объект RealTimeStylus сначала отключается до добавления или удаления подключаемых модулей, а затем снова включается после завершения добавления или удаления.
private void RemoveFromPluginCollection(int index)
{
IStylusSyncPlugin plugin = ((PluginListItem)chklbPlugins.Items[index]).Plugin;
bool rtsEnabled = myRealTimeStylus.Enabled;
myRealTimeStylus.Enabled = false;
myRealTimeStylus.SyncPluginCollection.Remove(plugin);
myRealTimeStylus.Enabled = rtsEnabled;
}
Связанные разделы
-
Плагины и класс RealTimeStylus
-
Пример коллекции рукописного ввода RealTimeStylus